from cytoolz.curried import assoc, compose, remove, pipe, merge_with, merge
from genomoncology.parse.doctypes import DocType, __CHILD__, __TYPE__
from genomoncology.pipeline.transformers import register, name_mapping


NAME_MAPPING = {
    "gene": "gene",
    "gene_mim__string": "Mim Number",
    "phenotype__mstring": "phenotype",
    "phenotype_mim__mstring": "phenotype_mim",
    "inheritance__mstring": "inheritance",
}


def split_filter(value, delimiter, pred_func):
    return filter(pred_func, value.split(delimiter))


def split_remove(value, delimiter, pred_func):
    return remove(pred_func, value.split(delimiter))


def parse_omim_inheritance(omim_pheno_d):
    omim_inheritance_l = [
        "Multifactorial",
        "autosomal dominant",
        "X-linked dominant",
        "X-linked",
        "X-linked recessive",
        "Y-linked",
        "autosomal recessive",
        "Autosomal dominant",
        "Autosomal recessive",
    ]
    omim_pheno_d = assoc(
        omim_pheno_d,
        "inheritance",
        ";".join(
            split_filter(
                omim_pheno_d["phenotype"],
                ", ",
                lambda x: x in omim_inheritance_l,
            )
        ),
    )
    omim_pheno_d = assoc(
        omim_pheno_d,
        "phenotype",
        ", ".join(
            split_remove(
                omim_pheno_d["phenotype"],
                ", ",
                lambda x: x in omim_inheritance_l,
            )
        ),
    )
    return omim_pheno_d


def parse_omim_position(omim_pheno_d):
    omim_position_l = ["(1)", "(2)", "(3)", "(4)"]
    omim_pheno_d = assoc(
        omim_pheno_d,
        "phenotype",
        " ".join(
            split_remove(
                omim_pheno_d["phenotype"], " ", lambda x: x in omim_position_l
            )
        ),
    )
    return omim_pheno_d


def parse_omim_pheno_id(omim_pheno_d):
    if omim_pheno_d["phenotype"][-6:].isdigit():
        omim_pheno_d = assoc(
            omim_pheno_d, "phenotype_mim", omim_pheno_d["phenotype"][-6:]
        )
        omim_pheno_d = assoc(
            omim_pheno_d, "phenotype", omim_pheno_d["phenotype"][:-8]
        )
    else:
        omim_pheno_d = assoc(omim_pheno_d, "phenotype_mim", "")
    return omim_pheno_d


def phenotype_pipeline(x):
    return pipe(
        {"phenotype": x},
        parse_omim_inheritance,
        parse_omim_position,
        parse_omim_pheno_id,
    )


def parse_omim_phenotypes(x):
    if "Phenotypes" in x:
        return merge_with(
            list, map(phenotype_pipeline, x["Phenotypes"].split("; "))
        )
    else:
        return x


def parse_omim_gene(x):
    return x["Gene Symbols"].split(", ")[0]


register(
    input_type=DocType.TSV,
    output_type=DocType.OMIM,
    transformer=compose(
        lambda x: assoc(x, "is_gene_annotation", True),
        lambda x: assoc(x, __TYPE__, DocType.OMIM.value),
        name_mapping(NAME_MAPPING),
        lambda x: merge(x, parse_omim_phenotypes(x)),
        lambda x: assoc(x, "gene", parse_omim_gene(x)),
        # name_mapping(NAME_MAPPING_PRE),
    ),
)

register(
    input_type=DocType.TSV,
    output_type=DocType.OMIM,
    transformer=compose(
        lambda x: assoc(x, "is_gene_annotation", True),
        lambda x: assoc(x, __CHILD__, DocType.OMIM.value),
        # lambda x: merge(x, parse_omim_phenotypes(x)),
    ),
    is_header=True,
)
