#!/usr/bin/python3
# SPDX-License-Identifier: AGPL-3.0-or-later
"""
Configuration helper for ikiwiki
"""

import argparse
import os
import re
import shutil
import subprocess
import sys

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')

    # 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.')

    subparsers.required = True
    return parser.parse_args()


def _is_safe_path(basedir, path):
    """Return whether a path is safe."""
    return os.path.realpath(path).startswith(basedir)


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


def get_title(site):
    """Get blog or wiki title"""
    try:
        with open(os.path.join(SITE_PATH, site, 'index.html')) as index_file:
            match = re.search(r'<title>(.*)</title>', index_file.read())
            if match:
                return match[1]
    except FileNotFoundError:
        pass

    return site


def subcommand_get_sites(_):
    """Get wikis and blogs."""
    if os.path.exists(SITE_PATH):
        for site in os.listdir(SITE_PATH):
            if not os.path.isdir(os.path.join(SITE_PATH, site)):
                continue

            title = get_title(site)
            print(site, title)


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,
                            env=dict(os.environ, PERL_UNICODE='AS'))
    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,
                            env=dict(os.environ, PERL_UNICODE='AS'))
    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)

    if not (_is_safe_path(SITE_PATH, html_folder)
            and _is_safe_path(WIKI_PATH, wiki_folder)):
        print('Error: {0} is not a correct name.'.format(arguments.name))
        exit(1)

    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)


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()
