#!/usr/bin/env python
# -*- coding: utf-8 -*-


import sys
import os
import logging

import numpy
import pandas

import pyorganism
import pyorganism.regulation as pyreg

from itertools import izip

from fuzzywuzzy import fuzz

from pyorganism.io.microarray import read_microarray


LOGGER = logging.getLogger()
LOGGER.addHandler(logging.StreamHandler())
LOGGER.setLevel(logging.INFO)

VERSION = "default"


single_dir = "Expression/LZ41-LZ54_single_knockouts"
double_dir = "Expression/LZ41-LZ54_double_knockouts"
CONFIG = dict(
        continuous=False,
        data_paths=[
            (os.path.join(single_dir, "LZ41-LZ54.tsv"), "wt"),
            (os.path.join(single_dir, "LZ41_d_fis-LZ54_d_fis.tsv"), "fis"),
            (os.path.join(single_dir, "LZ41_d_hns-LZ54_d_hns.tsv"), "hns"),
            (os.path.join(single_dir, "LZ41-LZ41_d_fis.tsv"), "wt-fis-low"),
            (os.path.join(single_dir, "LZ54-LZ54_d_fis.tsv"), "wt-fis-high"),
            (os.path.join(single_dir, "LZ41-LZ41_d_hns.tsv"), "wt-hns-low"),
            (os.path.join(single_dir, "LZ54-LZ54_d_hns.tsv"), "wt-hns-high"),
            (os.path.join(double_dir, "LZ41_d_fis_hns-LZ54_d_fis_hns.tsv"), "fis-hns"),
            (os.path.join(double_dir, "LZ41-LZ41_d_fis_hns.tsv"), "wt-fis-hns-low"),
            (os.path.join(double_dir, "LZ54-LZ54_d_fis_hns.tsv"),
                    "wt-fis-hns-high"),
        ],
        data_load=[
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray,
            read_microarray
        ],
        threshold=80
)


def compile_names(experiment_paths, loading_funcs):
    LOGGER.info("Loading discrete expression data")
    data_frames = [load_data(path)\
            for ((path, name), load_data) in izip(experiment_paths, loading_funcs)]
    return pandas.concat(data_frames, ignore_index=True)

def compile_feature_map(genes, features, gene_finder):
    feature2gene = dict()
    gap = list()
    for name in features:
        try:
            feature2gene[name] = gene_finder(name)
        except IndexError:
            gap.append(name)
    LOGGER.info("Found %d/%d (%3.2f%%)", len(feature2gene), len(features),
            100.0 * len(feature2gene) / len(features))
    return (feature2gene, gap)

def extend_feature_map(feature2gene, gap, gene_finder):
    found = list()
    for name in gap:
        try:
            feature2gene[name] = gene_finder(name)
            found.append(name)
        except IndexError:
            continue
    gap = set(gap).difference(set(found))
    LOGGER.info("Found %d additional genes", len(found))
    return gap

def fuzzy_extension(feature2gene, gap, gene_finder, thresh=80):
    found = list()
    for name in gap:
        try:
            (gene, match, score) = gene_finder.fuzzy_search(name,
                    threshold=thresh, scorer=fuzz.QRatio)
            feature2gene[name] = gene
            found.append(name)
        except IndexError:
            LOGGER.debug("'%s' not found", name)
            feature2gene[name] = None
    gap = set(gap).difference(set(found))
    LOGGER.info("Found %d additional genes", len(found))
    return gap

def synonym_finder(genes):
    targets = list()
    indeces = list()
    for (i, gene) in enumerate(genes):
        if gene.bnumber:
            targets.append(gene.bnumber)
            indeces.append(i)
        for name in gene.synonyms:
            targets.append(name)
            indeces.append(i)
#        if gene.product:
#            targets.append(gene.product.name)
#            indeces.append(i)
#            for name in gene.product.synonyms:
#                targets.append(name)
#                indeces.append(i)
#        if gene.regulatory_product:
#            targets.append(gene.regulatory_product.name)
#            indeces.append(i)
#            for name in gene.regulatory_product.synonyms:
#                targets.append(name)
#                indeces.append(i)
    return pyorganism.FindObject(genes, targets=targets, indeces=indeces)

def manual_name_updates(name2gene):
# [b1500](http://regulondb.ccg.unam.mx/gene?term=ECK120003379&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120003379", None, VERSION)
    name2gene["b1500"] = gene
# [b0609](http://regulondb.ccg.unam.mx/gene?term=ECK120002943&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120002943", None, VERSION)
    name2gene["b0609"] = gene
# [b0332](http://www.ncbi.nlm.nih.gov/gene/?term=944992) is not recorded in RegulonDB.
# [b3975](http://regulondb.ccg.unam.mx/gene?term=G7818&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120004318", None, VERSION)
    name2gene["b3975"] = gene
# [b2084](http://regulondb.ccg.unam.mx/gene?term=G7121&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120003706", None, VERSION)
    name2gene["b2084"] = gene
# [b0322](http://regulondb.ccg.unam.mx/gene?term=G0-10550&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120026444", None, VERSION)
    name2gene["b0322"] = gene
# [b0309](http://regulondb.ccg.unam.mx/gene?term=ECK120002798&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120002798", None, VERSION)
    name2gene["b0309"] = gene
# [b2596](http://regulondb.ccg.unam.mx/gene?term=G7353&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120003922", None, VERSION)
    name2gene["b2596"] = gene
# [b1364](http://regulondb.ccg.unam.mx/gene?term=ECK120003282&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120003282", None, VERSION)
    name2gene["b1364"] = gene
# [b4091](http://porteco.org/AjaxSearch.jsp?searchString=b4091) is not recorded in RegulonDB.
    gene = pyreg.Gene.get("ECK120003116", None, VERSION)
    name2gene["ycdF"] = gene
# [ycdF](http://regulondb.ccg.unam.mx/gene?term=ECK120003116&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120003116", None, VERSION)
    name2gene["ycdF"] = gene
# [b1903](http://regulondb.ccg.unam.mx/gene?term=G7034&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120003620", None, VERSION)
    name2gene["b1903"] = gene
# [b0501](http://regulondb.ccg.unam.mx/gene?term=G6272&type=gene&format=jsp)
    gene = pyreg.Gene.get("ECK120002880", None, VERSION)
    name2gene["b0501"] = gene
# [b0165](http://regulondb.ccg.unam.mx/gene?term=ECK120002711&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120002711", None, VERSION)
    name2gene["b0165"] = gene
# [rhsC_1](http://regulondb.ccg.unam.mx/gene?term=ECK120000839&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120000839", None, VERSION)
    name2gene["rhsC_1"] = gene
# [rhsC_2](http://regulondb.ccg.unam.mx/gene?term=ECK120000839&organism=ECK12&format=jsp&type=gene)
    gene = pyreg.Gene.get("ECK120000839", None, VERSION)