#!/usr/bin/python3
# pylint: disable=invalid-name  # https://github.com/PyCQA/pylint/issues/516
import json
import datetime
import logging

import dateutil.parser

import mini_buildd.api
import mini_buildd.client
import mini_buildd.events
import mini_buildd.cli

LOG = logging.getLogger("mini_buildd")

#: Needed for man page hack in setup.py
DESCRIPTION = "Run API calls and monitor events"


def parse_since(date_string):
    if date_string == "all":
        since = datetime.datetime(datetime.MINYEAR + 1, 1, 1)
        return since.astimezone()
    since = dateutil.parser.parse(date_string)
    if mini_buildd.misc.datetime_is_naive(since):
        since = since.astimezone()
        LOG.info(f"Naive timestamp converted: {date_string} => {since}")
    return since


class CLI(mini_buildd.cli.CLI):
    def __init__(self):
        super().__init__("mini-buildd-client", DESCRIPTION,
                         "Note: Uses 'python-keyring' to persist passwords (see '~/.local/share/python_keyring/')")

        self.parser.add_argument("-J", "--json", action="store_true",
                                 help="use parsable json output")
        self.parser.add_argument("--auto-confirm", action="store_true",
                                 help="force-bypass extra confirmation (for confirmable commands)")
        self.parser.add_argument("--auto-save-passwords", action="store_true",
                                 help="don't ask before saving passwords (via python-keyring)")

        # Unfortunately, we cannot group the commands (yet), see http://bugs.python.org/issue14037, https://bugs.python.org/issue9341
        self.subparsers = self.parser.add_subparsers(title="API commands (run 'mini-buildd-client <cmd> --help' for full single command help)",
                                                     required=True,
                                                     metavar="<cmd> [options]")

        events = self._add_subparser(self.subparsers, "events", "Monitor events. Optionally stop when criteria is met.")
        self._add_endpoint(events)
        events.add_argument("-T", "--type", choices=[t.name for t in list(mini_buildd.events.Type)], action="append", help="Type filter")
        events.add_argument("-P", "--package", action="store", help="Package name filter")
        events.add_argument("-V", "--version", action="store", help="Version filter")
        events.add_argument("-M", "--minimal-version", action="store", help="Minimal version filter")
        events.add_argument("-D", "--distribution", action="store", help="Distribution filter")
        events.add_argument("-C", "--since", type=parse_since, action="store", help="Replay past events since this date (formats like 'date --iso-8601=ns' work fine). Use 'all' to replay all.")
        events.add_argument("-S", "--stop", action="store_true", default=False, help="Stop on 1st matching event")
        events.set_defaults(func=self.events)

        for cmd, cmd_cls in mini_buildd.api.COMMANDS.items():
            if not cmd_cls.isgroup():
                cmd_parser = self._add_subparser(self.subparsers, cmd, cmd_cls.doc() + "\n.")
                self._add_endpoint(cmd_parser)
                for argument in cmd_cls.ARGUMENTS:
                    cmd_parser.add_argument(*argument.id_list, **argument.argparse_kvsargs)
                cmd_parser.set_defaults(func=self.api, command=cmd)

    def events(self):
        client = mini_buildd.client.Client(self.args.endpoint)
        for event in client.events(types=self.args.type,
                                   package=self.args.package,
                                   version=self.args.version,
                                   minimal_version=self.args.minimal_version,
                                   distribution=self.args.distribution,
                                   since=self.args.since,
                                   stop=self.args.stop):
            print(json.dumps(event.to_json(), indent=2))

    def api(self):
        args = {k: self.args.__dict__[k] for k in mini_buildd.api.COMMANDS[self.args.command].arg_identities() if self.args.__dict__[k] is not None}
        result = mini_buildd.client.Client(self.args.endpoint,
                                           auto_confirm=self.args.auto_confirm,
                                           auto_save_passwords=self.args.auto_save_passwords).api(self.args.command, args)
        print(json.dumps(result) if self.args.json else mini_buildd.api.Command.plain(result))

    def runcli(self):
        self.args.func()


CLI().run()
