import logging
import os
import sys

from snakemake import utils as smk_utils
from .vars import GENERAL_CFG_PATHS, PROPHANE_DIR, DEFAULT_GENERAL_CFG
from .input_output import load_yaml

logger = logging.getLogger(__name__)
logger.addHandler(logging.NullHandler())

INCONCLUSIVE_ANNOTATIONS = {
    'unclassified': 'unclassified',
    'heterogenous': 'various'
}


def amend_config_with_defaults(
        user_config_dict,
        default_config_dict
):
    # default_cfg = load_yaml(default_config_path)
    user_config_dict = smk_utils.update_config(default_config_dict, user_config_dict)
    return user_config_dict


def validate_config_and_set_defaults(config_dict, schema="schemas/config.schema.yaml"):
    """
    Validates  config_dict with against config schema.
    Sets default values if not set.
    :param config_dict: dictionary to be validated
    :param schema: yaml or json schema, can contain defaults
    :return: config dict with defaults for missing values
    """
    smk_utils.validate(config_dict, schema, set_default=True)
    return config_dict


def get_general_cfg_path():
    general_config_yaml = ""
    for path in GENERAL_CFG_PATHS:
        if os.path.isfile(path):
            general_config_yaml = path
            break
    if general_config_yaml == "":
        raise FileNotFoundError("No general config file found in the locations\n" + "\n".join(GENERAL_CFG_PATHS))
    return general_config_yaml


def read_general_config(general_config_yaml=""):
    if general_config_yaml == "":
        general_config_yaml = get_general_cfg_path()
    try:
        general_config = load_yaml(general_config_yaml)
    except FileNotFoundError:
        raise FileNotFoundError("No general config file found at any of the following locations:\n\t" +
                                "\n\t".join(GENERAL_CFG_PATHS) + "\n" +
                                "Aborting")
    print(f"Reading general config '{general_config_yaml}'", file=sys.stderr)
    smk_utils.validate(general_config,
                       schema=os.path.join(PROPHANE_DIR, "schemas", "general_config.schema.yaml"))
    return general_config


def get_database_base_dir(job_config=None, config_dict=None):
    """
    Get the absolute path of the database base dir. The following places are checked for the path and the first hit
    is returned:
    - config_dict
    - job_config
    - general_config

    :param job_config: path or dict
    :param config_dict: dictionary
    :return: path, absolute path to database base dir
    """
    k = 'db_base_dir'
    job_config_dict = None

    db_path = None

    if job_config:
        if os.path.isfile(job_config):
            job_config_dict = load_yaml(job_config)
        else:
            job_config_dict = job_config

    for cfg in [config_dict, job_config_dict]:
        if cfg:
            if k in cfg:
                db_path = cfg[k]
                break

    if not db_path:
        try:
            cfg = read_general_config()
        except FileNotFoundError as e:
            raise LookupError(f"Config parameter '{k}' not found in any config.")
        else:
            db_path = cfg[k]

    db_path_abs = os.path.abspath(db_path)
    return db_path_abs
