#!/usr/bin/python3
#
# This file is part of Plinth.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

"""
Configuration helper for ikiwiki
"""

import argparse
import os
import shutil
import subprocess
import sys

from plinth import action_utils


SETUP_WIKI = '/etc/ikiwiki/plinth-wiki.setup'
SETUP_BLOG = '/etc/ikiwiki/plinth-blog.setup'
SITE_PATH = '/var/www/ikiwiki'
WIKI_PATH = '/var/lib/ikiwiki'


def parse_arguments():
    """Return parsed command line arguments as dictionary."""
    parser = argparse.ArgumentParser()
    subparsers = parser.add_subparsers(dest='subcommand', help='Sub command')

    # Setup ikiwiki site
    subparsers.add_parser('setup', help='Perform first time setup operations')

    # Enable ikiwiki site
    subparsers.add_parser('enable', help='Enable ikiwiki site')

    # Disable ikiwiki site
    subparsers.add_parser('disable', help='Disable ikiwiki site')

    # Get wikis and blogs
    subparsers.add_parser('get-sites', help='Get wikis and blogs')

    # Create a wiki
    create_wiki = subparsers.add_parser('create-wiki', help='Create a wiki')
    create_wiki.add_argument('--wiki_name', help='Name of new wiki')
    create_wiki.add_argument('--admin_name', help='Administrator account name')

    # Create a blog
    create_blog = subparsers.add_parser('create-blog', help='Create a blog')
    create_blog.add_argument('--blog_name', help='Name of new blog')
    create_blog.add_argument('--admin_name', help='Administrator account name')

    # Delete a wiki or blog
    delete = subparsers.add_parser('delete', help='Delete a wiki or blog.')
    delete.add_argument('--name', help='Name of wiki or blog to delete.')

    return parser.parse_args()


def subcommand_setup(_):
    """Perform first time setup operations."""
    setup()


def subcommand_enable(_):
    """Enable ikiwiki site."""
    action_utils.webserver_enable('ikiwiki-plinth')


def subcommand_disable(_):
    """Disable ikiwiki site."""
    action_utils.webserver_disable('ikiwiki-plinth')


def subcommand_get_sites(_):
    """Get wikis and blogs."""
    try:
        sites = os.listdir(SITE_PATH)
        print('\n'.join(sites))
    except FileNotFoundError:
        pass


def subcommand_create_wiki(arguments):
    """Create a wiki."""
    pw_bytes = sys.stdin.read().encode()
    proc = subprocess.Popen(
        ['ikiwiki', '-setup', SETUP_WIKI,
         arguments.wiki_name, arguments.admin_name],
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    outs, errs = proc.communicate(input=pw_bytes + b'\n' + pw_bytes)
    print(outs)
    print(errs)


def subcommand_create_blog(arguments):
    """Create a blog."""
    pw_bytes = sys.stdin.read().encode()
    proc = subprocess.Popen(
        ['ikiwiki', '-setup', SETUP_BLOG,
         arguments.blog_name, arguments.admin_name],
        stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
    outs, errs = proc.communicate(input=pw_bytes + b'\n' + pw_bytes)
    print(outs)
    print(errs)


def subcommand_delete(arguments):
    """Delete a wiki or blog."""
    html_folder = os.path.join(SITE_PATH, arguments.name)
    wiki_folder = os.path.join(WIKI_PATH, arguments.name)

    try:
        shutil.rmtree(html_folder)
        shutil.rmtree(wiki_folder)
        shutil.rmtree(wiki_folder + '.git')
        os.remove(wiki_folder + '.setup')
        print('Deleted {0}'.format(arguments.name))
    except FileNotFoundError:
        print('Error: {0} not found.'.format(arguments.name))
        exit(1)


def setup():
    """Write Apache configuration and wiki/blog setup scripts."""
    if not os.path.exists(SITE_PATH):
        os.makedirs(SITE_PATH)

    with action_utils.WebserverChange() as webserver_change:
        webserver_change.enable('cgi', kind='module')
        webserver_change.enable('authnz_ldap', kind='module')
        webserver_change.enable('ikiwiki-plinth')


def main():
    """Parse arguments and perform all duties."""
    arguments = parse_arguments()

    subcommand = arguments.subcommand.replace('-', '_')
    subcommand_method = globals()['subcommand_' + subcommand]
    subcommand_method(arguments)


if __name__ == '__main__':
    main()
