import sys
from argparse import ArgumentParser

from yamlargs.config import YAMLConfig


def create_parser(config: YAMLConfig) -> ArgumentParser:
    """
    Automatically creates a parser from all of the values specified in a config
    file. Will use the dot syntax for nested dictionaries.

    Parameters
    ----------
    config: YAMLConfig
        Config object

    Returns
    -------
    ArgumentParser
        Parser loaded up with all of the values specified in the config
    """
    key_pairs = config.keys()

    parser = ArgumentParser(
        description=f"""
This argument parser was autogenerated from the config file. This allows you to
overwrite specific YAML values on the fly. The options listed here do not
entail an exhaustive list of the things that you can configure. For more
information on possible kwargs, refer to the class definition of the object in
question. 
    """
    )

    parser.add_argument(f"config_file", help="YAML config file")
    for k in key_pairs:
        current = config.access(k)
        parser.add_argument(f"--{k}", type=type(current))

    return parser


def load_config_and_create_parser():
    """
    Loads a config and creates a parser.

    Use this to initialize everything when you want to add more arguments to
    the parser. Will load the config from the first sys.argv position.

    Returns
    -------
    YAMLConfig
        config object loaded from sys.argv[1]
    ArgumentParser
        Parser for the loaded config object
    """
    path = sys.argv[1]
    config = YAMLConfig.load(path)
    parser = create_parser(config)
    return config, parser


def parse_args_into_config(config, args, verbose=False):
    """"""
    for (k, v) in vars(args).items():
        if v and k != "config_file":
            config.set(k, v)

    if verbose:
        print(config)

    return config


def load_config_and_parse_cli(verbose=False):
    """
    Loads a config and parses all the command line arguments.

    One stop shop, will handle all of the intialization for you. Loads the
    config from sys.argv[1], creates an ArugmentParser, and then parses the
    specified args.

    Returns
    -------
    YAMLConfig
        Fully loaded config object
    """
    config, parser = load_config_and_create_parser()
    args = parser.parse_args()
    config = parse_args_into_config(config, args, verbose=verbose)
    return config
