#!/usr/bin/env python3

import argparse
import pandas as pd
import numpy as np
import json
import sys
import os
import time

import matplotlib
matplotlib.use('Agg')
import logging

import importlib.resources as importlib_resources

from miner import miner, util, GIT_SHA
from miner import __version__ as MINER_VERSION
from miner import coexpression, mechinf


DESCRIPTION = """miner3-mechinf - MINER compute mechanistic inference
MINER Version %s (Git SHA %s)""" % (str(MINER_VERSION).replace('miner3 ', ''),
                                    GIT_SHA.replace('$Id: ', '').replace(' $', ''))

if __name__ == '__main__':
    logging.getLogger('matplotlib.font_manager').disabled = True
    LOG_FORMAT = '%(asctime)s %(message)s'
    logging.basicConfig(format=LOG_FORMAT, level=logging.DEBUG,
                        datefmt='%Y-%m-%d %H:%M:%S \t')

    parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
                                     description=DESCRIPTION)
    parser.add_argument('expfile', help="input matrix")
    parser.add_argument('mapfile', help="identifier mapping file")
    parser.add_argument('outdir', help="output directory")

    # mechinf optional parameters
    parser.add_argument('-mc', '--mincorr', type=float, default=0.2,
                        help="minimum correlation")
    parser.add_argument('--skip_tpm', action="store_true",
                        help="overexpression threshold")
    parser.add_argument('--firmout', default='miner_exported_regulons.sgn',
                        help='file name for FIRM input file, will be stored in outdir')
    parser.add_argument('--genelist', default='all_genes.txt',
                        help='file name for the gene file, will be stored in outdir')
    parser.add_argument('--tfs2genes', default=None,
                        help='Transcription factor to gene mapping file, either JSON or pkl')

    # coexpression optional parameters
    parser.add_argument('-mg', '--mingenes', type=int, default=6, help="min number genes")
    parser.add_argument('-moxs', '--minoverexpsamp', type=int, default=4,
                        help="minimum overexpression samples")
    parser.add_argument('-mx', '--maxexclusion', type=float, default=0.5,
                        help="maximum samples excluded")
    parser.add_argument('-rs', '--randstate', type=int, default=12,
                        help="random state")
    parser.add_argument('-oxt', '--overexpthresh', type=int, default=80,
                        help="overexpression threshold")

    args = parser.parse_args()

    if not os.path.exists(args.expfile):
        sys.exit("expression file not found")
    if not os.path.exists(args.mapfile):
        sys.exit("identifier mapping file not found")
    if not os.path.exists(args.outdir):
        os.makedirs(args.outdir)
    with open(os.path.join(args.outdir, 'run_info.txt'), 'w') as outfile:
        util.write_dependency_infos(outfile)

    exp_data, conv_table = miner.preprocess(args.expfile, args.mapfile, do_preprocess_tpm=(not args.skip_tpm))

    revised_clusters = coexpression.coexpression(exp_data, args.outdir,
                                                 args.skip_tpm,
                                                 args.mingenes,
                                                 args.minoverexpsamp,
                                                 args.maxexclusion,
                                                 args.overexpthresh,
                                                 args.randstate)

    if args.tfs2genes is not None:
        database_path = args.tfs2genes
    else:
        try:
            database_path = importlib_resources.files("miner").joinpath("data", "network_dictionaries",
                                                                        "tfbsdb_tf_to_genes.pkl")
            database_path = str(database_path)  # turn into str object
        except:
            # running from source
            database_path = os.path.join('miner', 'data', 'network_dictionaries', 'tfbsdb_tf_to_genes.pkl')
            print("DATABASE PATH (FROM ERROR): ", database_path)

    mechinf.mechanistic_inference(exp_data, args.mapfile, revised_clusters,
                                  database_path,
                                  args.outdir,
                                  args.mincorr, args.skip_tpm, args.firmout,
                                  args.genelist)
