#!/usr/bin/env python3

import argparse

from compose_cms import Compose
from compose_cms.utils import compose_type_to_python_type


class NotNone:
    pass


class Usage:

    def __init__(self, name):
        self.usage = [name]

    def __call__(self, *args, **kwargs):
        self.usage.extend(args)
        return self

    def __str__(self):
        return ' '.join(self.usage)


def _package(usage, args, compose):
    parser = argparse.ArgumentParser(usage=str(usage('--package <package>')))
    parser.add_argument(
        '--package',
        help='Package ID',
        choices=compose.packages,
        required=True
    )
    parsed, remaining = parser.parse_known_args(args=args)
    # ---
    return compose.package(parsed.package), remaining


def _page(usage, args, compose):
    package, _ = _package(usage, args, compose)
    parser = argparse.ArgumentParser(usage=str(usage('--page <page>')))
    parser.add_argument(
        '--page',
        help='Page ID',
        choices=package.pages,
        required=True
    )
    parsed, remaining = parser.parse_known_args(args=args)
    # ---
    return package.page(parsed.page), remaining


def _configuration(usage, args, compose):
    parser = argparse.ArgumentParser(usage=str(usage))
    package, args = _package(usage, args, compose)
    configuration = package.configuration()
    for key, info in configuration.metadata.items():
        ptype = compose_type_to_python_type(info['type'])
        parser.add_argument(
            '--{}'.format(key),
            type=ptype,
            const=NotNone,
            nargs='?',
            help=info['details']
        )
    parsed = parser.parse_args(args=args)
    given = {k: v for k, v in vars(parsed).items() if v is not None}
    return given, []


def package_enable(usage, args, compose):
    package, _ = _package(usage, args, compose)
    package.enable()


def package_disable(usage, args, compose):
    package, _ = _package(usage, args, compose)
    package.disable()


def page_enable(usage, args, compose):
    page, _ = _page(usage, args, compose)
    page.enable()


def page_disable(usage, args, compose):
    page, _ = _page(usage, args, compose)
    page.disable()


def configuration_get(usage, args, compose):
    package, _ = _package(usage, args, compose)
    keys, _ = _configuration(usage, args, compose)
    configuration = package.configuration()
    for key in keys:
        value = configuration.get(key)
        print('{}={}'.format(key, str(value)))


def configuration_set(usage, args, compose):
    package, _ = _package(usage, args, compose)
    cfg, _ = _configuration(usage, args, compose)
    configuration = package.configuration()
    for key, value in cfg.items():
        configuration.set(key, value)


SUPPORTED_ACTIONS = {
    'package/enable': package_enable,
    'package/disable': package_disable,
    'page/enable': page_enable,
    'page/disable': page_disable,
    'configuration/get': configuration_get,
    'configuration/set': configuration_set,
}


if __name__ == '__main__':
    _usage = Usage('compose')
    _parser = argparse.ArgumentParser(usage=str(_usage))
    # ---
    _parser.add_argument('--action', '-a',
                         choices=SUPPORTED_ACTIONS.keys(),
                         required=True,
                         help='Action to perform')
    _parser.add_argument('--workspace', '-C',
                         default=None,
                         help='Directory where \\compose\\ is installed')
    _parser.add_argument('--userdata', '-U',
                         default=None,
                         help='Directory containing the user-data')
    _parsed, _remaining = _parser.parse_known_args()
    # execute action
    _compose = Compose(path=_parsed.workspace, userdata=_parsed.userdata)
    SUPPORTED_ACTIONS[_parsed.action](_usage, _remaining, _compose)
