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

import sys
import inspect
import argparse
import json
import logging

import argcomplete

import mini_buildd.misc
import mini_buildd.net
import mini_buildd.config
import mini_buildd.api

LOG = logging.getLogger("mini_buildd")
mini_buildd.misc.setup_console_logging(logging.DEBUG)

PARSER = argparse.ArgumentParser(prog="mini-buildd-api",
                                 description="Command line tool to run API calls.",
                                 epilog="Note: Uses 'python-keyring' to persist passwords (see '~/.local/share/python_keyring/')",
                                 formatter_class=mini_buildd.misc.ArgumentDefaultsRawTextHelpFormatter)
PARSER.add_argument("--version", action="version", version=mini_buildd.__version__)
PARSER.add_argument("-v", "--verbose", dest="verbosity", action="count", default=0,
                    help="increase log level. Give twice for max logs")
PARSER.add_argument("-q", "--quiet", dest="terseness", action="count", default=0,
                    help="decrease log level. Give twice for min logs")
PARSER.add_argument("-J", "--json", action="store_true",
                    help="use parsable json output")
PARSER.add_argument("--auto-confirm", action="store_true",
                    help="force-bypass extra confirmation (for confirmable commands)")
PARSER.add_argument("--auto-save-passwords", action="store_true",
                    help="don't ask before saving passwords (via python-keyring)")


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


# Unfortunaetely, we cannot group the commands (yet), see http://bugs.python.org/issue14037, https://bugs.python.org/issue9341
SUBPARSERS = PARSER.add_subparsers(title="API commands (run 'mini-buildd-api <cmd> --help' for full single command help)",
                                   required=True,
                                   metavar="<cmd> [options]")
for cmd, cmd_cls in mini_buildd.api.COMMANDS.items():
    if not cmd_cls.isgroup():
        cmd_parser = SUBPARSERS.add_parser(cmd, help=cmd_cls.doc() + "\n.", formatter_class=mini_buildd.misc.ArgumentDefaultsRawTextHelpFormatter)
        cmd_parser.add_argument("endpoint", action="store",
                                metavar="ENDPOINT",
                                help=f"HTTP target endpoint: {inspect.getdoc(mini_buildd.net.ClientEndpoint)}\n\nMay also be '[user@]DPUT_TARGET' for convenience").completer = lambda **kwargs: mini_buildd.misc.DputCf().urls()
        for argument in cmd_cls.ARGUMENTS:
            cmd_parser.add_argument(*argument.id_list, **argument.argparse_kvsargs)
        cmd_parser.set_defaults(func=api_call, command=cmd)


# Parse and run
argcomplete.autocomplete(PARSER)
ARGS = PARSER.parse_args()
LOG.setLevel(logging.WARNING - (10 * (min(2, ARGS.verbosity) - min(2, ARGS.terseness))))

if LOG.getEffectiveLevel() <= logging.DEBUG:
    mini_buildd.config.DEBUG = ["exception"]

try:
    ARGS.func(ARGS)
except BaseException as e:
    mini_buildd.config.log_exception(LOG, "mini-buildd-api failed (try '-vv' to debug)", e)
    sys.exit(1)
