import os
import oyaml as yaml
from .exceptions import ConfigurationError
from .constants import crv_def, crx_def, crg_def


class AnnotatorOptions(object):
    valid_levels = ["variant", "gene"]
    valid_input_formats = ["crv", "crx", "crg"]
    id_col_defs = {"variant": crv_def[0], "gene": crg_def[0]}
    default_input_columns = {
        "crv": [x["name"] for x in crv_def],
        "crx": [x["name"] for x in crx_def],
        "crg": [x["name"] for x in crg_def],
    }
    required_conf_keys = ["level", "output_columns"]

    def __init__(self, annotator_dir):
        self.secondary_inputs = {}
        self.secondary_paths = {}
        self.annotator_dir = os.path.abspath(annotator_dir)
        self.annotator_name = os.path.basename(self.annotator_dir)
        self.annotator_conf_path = os.path.join(
            self.annotator_dir, self.annotator_name + ".yml"
        )

    # Parse the default conf files and the optional job conf
    def parse_all_conf_files(self):
        self.parse_conf_file(self.annotator_conf_path)
        # TODO parse cravat.conf if available
        if self.job_conf_path:
            self.parse_conf_file(self.job_conf_path)

    # Parse just the annotator conf file
    def parse_annotator_conf(self):
        self.parse_conf_file(self.annotator_conf_path)

    # Parse a generic conf file.
    # Apply special parsing rules to certain conf keys
    def parse_conf_file(self, conf_path):
        d = yaml.safe_load(open(conf_path))
        for k in self.required_conf_keys:
            if k not in d:
                err_msg = 'Required key "%s" not found in configuration' % k
                raise ConfigurationError(err_msg)
        if d["level"] in self.valid_levels:
            d["output_columns"] = [self.id_col_defs[d["level"]]] + d["output_columns"]
        else:
            err_msg = "%s is not a valid level. Valid levels are %s" % (
                d["level"],
                ", ".join(self.valid_levels),
            )
            raise ConfigurationError(err_msg)
        if "input_format" in d:
            if d["input_format"] not in self.valid_input_formats:
                err_msg = "Invalid input_format %s, select from %s" % (
                    d["input_format"],
                    ", ".join(self.valid_input_formats),
                )
        else:
            if d["level"] == "variant":
                d["input_format"] = "crv"
            elif d["level"] == "gene":
                d["input_format"] = "crg"
        if "input_columns" in d:
            id_col_name = self.id_col_defs[d["level"]]["name"]
            if id_col_name not in d["input_columns"]:
                d["input_columns"].append(id_col_name)
        else:
            d["input_columns"] = self.default_input_columns[d["input_format"]]
        for k, v in d.items():
            self.__dict__[k] = v

    def __getitem__(self, key):
        return self.__dict__[key]

    def __setitem__(self, key, value):
        self.__dict__[key] = value
