import os, time
start = time.time()
from importlib.resources import files
from scipy.spatial.distance import squareform

from py_report_html.py_report_html import Py_report_html
from py_cmdtabs.cmdtabs import CmdTabs
from py_exp_calc.exp_calc import *

def main_stable_select(args):
    import pandas as pd
    data = pd.read_csv(
        args["input"],
        sep=args["sep"],
        header=args["header"],
        index_col=args["index_col"]
    )
    label = pd.read_csv(args["label"], header=None)

    new_table = stable_selection(
        data,
        label,
        regularization_strength=args["regularization_strength"],
        l1_ratio=args["l1_ratio"],
        number_iter=args["number_iter"],
        sample_fraction=args["sample_fraction"],
        proportion_threshold=args["proportion_threshold"],
        random_state=args["random_state"],
        return_stability=args["return_stability"]
    )

    new_table.to_csv(args["output"], sep="\t", index=True, header=True)

def main_inference_analyzer(args):
    table = CmdTabs.load_input_data(args['input'])
    table = parse_table(table, header=args['header'], factor_index= args['factor_indexes'])
    stats = get_test(table, args['factor_indexes'], alternative = args['alt_hyp'], header = args["header"], adj_pval=args['adj_pval'], parametric = not args['no_parametric'])
    CmdTabs.write_output_data(stats, output_path=args['output'])

def main_clusterize(args):
    import numpy as np

    observation_matrix, y_names, x_names = load(args['input'], 
        x_axis_file=args['x_dim'], y_axis_file=args['y_dim'])


    if len(observation_matrix.shape) == 1: # transform 1 Dimensional array to 2 Dimensional array
        observation_matrix = observation_matrix.reshape(observation_matrix.size, 1)
    if args['clustering'] == 'kmeans':
        from sklearn.cluster import KMeans
        kmeans = KMeans(n_clusters=args['n_clusters'], random_state=0, n_init="auto").fit(observation_matrix)
        with open(args['output'], 'w') as f:
            for i, cluster_id in enumerate(kmeans.labels_): f.write(f"{x_names[i]}\t{cluster_id}\n")
    elif args['clustering'] == 'mbk':
        from sklearn.cluster import MiniBatchKMeans
        mbk = MiniBatchKMeans(init='k-means++', n_clusters=args['n_clusters'], batch_size=1024,
                      n_init=10, max_no_improvement=10, verbose=0).fit(observation_matrix)
        with open(args['output'], 'w') as f:
            for i, cluster_id in enumerate(mbk.labels_): f.write(f"{x_names[i]}\t{cluster_id}\n")
    else:
        clusters, cls_objects = get_hc_clusters(observation_matrix, identify_clusters=args['clustering'], item_list = x_names, n_clusters= args['n_clusters'])
        write_dict(clusters, args['output'])
        if args['report']:
            template = open(str(files('py_exp_calc.templates').joinpath('clustering.txt'))).read()
            container = {   'dist': squareform(cls_objects['dist_vector']), 
                            'link': cls_objects['link'], 
                            'raw_cls': cls_objects['cls'] }
            report = Py_report_html(container, 'Clustering')
            report.build(template)
            report.write(os.path.join(os.path.dirname(args["output"]), 'clustering.html'))

def read_tabular_file(input_file, cols):
    data = []
    with open(input_file) as f:
        for line in f:
            fields = line.rstrip().split("\t")
            data.append([fields[i] for i in cols])
    return data

def write_dict(dict, file):
    with open(file, 'w') as f:
        for k, values in dict.items():
            f.write(f"{k}\t{','.join(values)}\n")

def parse_table(table, header, factor_index):
    parsed_table = []
    if header:
        header = table.pop(0)
    for row in table:
        parsed_row = []
        for idx, el in enumerate(row):
            if not idx in factor_index:
                parsed_row.append(float(el))
            else:
                parsed_row.append(el)
        parsed_table.append(parsed_row)
    table = parsed_table
    if header:
        table.insert(0, header)
    return table


def main_performancer(options):
    from py_exp_calc.performancer import Performancer
    controls = get_records(options['control_file'])
    predictions = get_records(options['input'])
    sample_ids = sorted(set([row[2] for row in controls]))
    metric_table = []
    summary_table = []
    for sample_id in sample_ids:
        controls_subset = [[row[0], row[1]] for row in controls if row[2] == sample_id]
        predictions_subset = [[row[0], row[1]] for row in predictions if row[2] == sample_id]
        factors = []
        if len(predictions[0]) > 3:
            factors = [row[3:] for row in predictions if row[2] == sample_id]
            factors = factors[0]
        performancer = Performancer()
        performancer.load_controls(controls_subset)
        performancer.load_predictions(predictions_subset)
        performancer.factors = factors
        # Creating metrics by score
        performancer.metrics_table_by_score( metrics=options["metrics"], descending=not options["ascending"], score_cut=np.inf, 
                                            add_factors=True, add_counts=False)
        df = performancer.metric_table
        df.insert(0, "sample_id", sample_id)
        if not metric_table:
            metric_table = [df.columns.tolist()]
        metric_table.extend(df.values.tolist())

        # Creating summary score
        summary = performancer.get_summary_metrics(
            best_for=options["metrics"], descending=not options["ascending"],
            add_factors=True
        )
        summary["sample_id"] = sample_id
        if not summary_table:
            factor_cols = sorted(k for k in summary.keys() if k.startswith("factor"))
            metric_cols = sorted(k for k in summary.keys() 
                                 if k not in factor_cols and k != "sample_id")
            header = ["sample_id"] + metric_cols + factor_cols
            summary_table.append(header)
        row_summary = [summary.get(col) for col in summary_table[0]]
        summary_table.append(row_summary)

    if options["generate_table"]:
        with open(options["output"] + "_table", "w") as f:
            for row in metric_table:
                row = [str(col) for col in row]
                f.write("\t".join(row) + "\n")

        with open(options["output"] + "_summary_table", "w") as f:
            for row in summary_table:
                row = [str(col) for col in row]
                f.write("\t".join(row) + "\n")

    if options["generate_report"]:
        template = open(str(files('py_exp_calc.templates').joinpath('performancer.txt'))).read()
        container = {'metrics_table': metric_table, 'summary_table': summary_table, 'metrics': options['metrics']}
        report = Py_report_html(container, 'Performance')
        report.build(template)
        report.write(options["output"]+'_report.html')

def get_records(file):
    return CmdTabs.load_input_data(file, autodetect_compression=True)
