#!python
import asyncio
import argparse
import logging
import logzero
import sys

from logzero import logger
from oliver.lib import api, args as _args, errors, config as _config
from oliver.subcommands import (
    aws,
    azure,
    aggregate,
    batches,
    configure,
    config,
    inputs,
    inspect,
    kill,
    logs,
    outputs,
    retry,
    runtime,
    status,
    submit,
)

SUBCOMMANDS = {
    "aws": aws,
    "azure": azure,
    "aggregate": aggregate,
    "batches": batches,
    "configure": configure,
    "config": config,
    "inputs": inputs,
    "inspect": inspect,
    "kill": kill,
    "logs": logs,
    "outputs": outputs,
    "retry": retry,
    "runtime": runtime,
    "status": status,
    "submit": submit,
}



def ensure_required_args(args):
    missing_args = []

    for a in _config.REQUIRED_ARGS:
        if not a in args or not args[a]:
            missing_args.append(a)

    if missing_args:
        errors.report(
            f"The following required arguments are missing: {', '.join(missing_args)}!\n\n" + \
            "We recommend you run 'oliver configure' to ensure all required arguments are cached in the oliver configuration file.\n" + \
            "If you choose not to do this, you will need to pass their respective flags on the command line.",
            fatal=True,
            exitcode=errors.ERROR_PRECAUTION,
        )


async def main():
    parser = argparse.ArgumentParser(
        description="An opinionated Cromwell orchestration system."
    )

    # Common arguments
    parser.add_argument("--cromwell-server", help="Cromwell host location.")
    parser.add_argument("--cromwell-api-version", help="Cromwell API version.")
    _args.add_loglevel_group(parser)

    # Subparsers
    subparsers = parser.add_subparsers(dest="subcommand")

    for name, module in SUBCOMMANDS.items():
        if not hasattr(module, "register_subparser") or not hasattr(module, "call"):
            errors.report(
                f"Subcommand does not have required methods: {name}!",
                fatal=True,
                exitcode=errors.ERROR_INTERNAL_ERROR,
            )
        subparser = module.register_subparser(subparsers)
        _args.add_loglevel_group(subparser)

    args = vars(parser.parse_args())

    for k, v in _config.read_config().items():
        # if the user has not supplied a parameter on the command line, add the default
        # value from the config to `args`.
        if not k in args or not args[k]:
            args[k] = v

    if args.get("subcommand") != "configure":
        ensure_required_args(args)

    if not args.get("subcommand"):
        parser.print_help()
        sys.exit(1)

    logzero.loglevel(logging.WARN)
    if args.get("verbose"):
        logzero.loglevel(logging.INFO)
    elif args.get("debug"):
        logzero.loglevel(logging.DEBUG)

    cromwell = api.CromwellAPI(server=args["cromwell_server"], version=args["cromwell_api_version"])
    await args["func"](args, cromwell)
    await cromwell.close()


if __name__ == "__main__":
    asyncio.run(main()) 