# IMPORTS
from plotnine import *  # ggplot
from decoder import *
from typing import Tuple, List

CRED = '\033[91m'  # RED COLOR
CGREEN = '\033[92m'  # GREEN COLOR
CEND = '\033[0m'  # END WITH COLORS


class Graphs:
    """
    Graphs class.
    Responsible for drawing and getting all of the data generated by the decoder class.
    """

    def __init__(self):
        """
        Ctor of the graphs class
        """
        pass

    @staticmethod
    def plot_acc_over_concat_cells(mega_files: Tuple[List[str]] = None, number_of_concat_cells: int = 100, ticks: int = 1):
        """
        Drawing a graphs of accuracies over number of concatenated cells, of all the populations selected.
        and of all of the experiment types.
        :param populations: Selected populations.
        :param experiment_types: experiment types.
        :param number_of_concat_cells: Number of cells to show !!!INCLUSIVE!!!. (X Axis ticks)
        :return: The filtered DataFrame.
        """

        for i,files in enumerate(mega_files):
            if (i==0):
                filtered_dataframe = decoder.get_acc_df_for_graph(files)
                filtered_dataframe.insert(0,"graph",[0 for j in range(filtered_dataframe.shape[0])],True)
            else:
                temp_df = decoder.get_acc_df_for_graph(files)
                temp_df.insert(0, "graph", [i for j in range(temp_df.shape[0])], True)
                filtered_dataframe = pd.concat([filtered_dataframe, temp_df],axis =0)

        print(ggplot(data=filtered_dataframe,
                     mapping=aes(x='concatenated_cells', y='acc', color='group', group='group')) + \
              geom_line() +
              geom_point() +
              facet_wrap('~graph') +
              scale_x_continuous(
                  breaks=np.arange(1, number_of_concat_cells + 1, ticks)) +  # X axis leaving out some ticks
              scale_y_continuous(breaks=np.arange(0, 1, 0.05)) +  # Y axis scaling
              labs(x='Number of concatenated cells', y='Accuracy') +
              theme_classic() +
              geom_errorbar(mapping=aes(x="concatenated_cells", ymin='acc-std', ymax='acc+std')))
        return filtered_dataframe

    @staticmethod
    def plot_histogram(files: List[str] = None):
        new_arr = []
        steps = np.arange(0, 1, 0.2)
        for step in steps:
            new_arr.append(str(int(step * 100)) + "% - " + str(int((step + 0.2) * 100)) + "%")

        for file in files:
            if os.path.isdir(file):
                if os.name == 'nt':  # windows
                    file = file + "\\"
                elif os.name == 'posix':  # Linux , Mac OSX and all the other posix compatible os.
                    file = file + "/"
                else:
                    file = file + "/"
                all_the_files = [os.path.dirname(file) + "/" + file2 for file2 in os.listdir(file)]
                all_the_files = [name for name in all_the_files if os.path.basename(name) in ALL_POSSIBILE_POPULATIONS]

            else:
                all_the_files = [file]
            for file2 in all_the_files:
                acc = []
                df = decoder.get_population_one_cell_data_frame(file2)
                total_num = df.shape[0]
                acc.append(df.loc[(df['acc'] >= 0) & (df['acc'] <= 0 + 0.2)].shape[0])
                acc.extend([df.loc[(df['acc'] > x) & (df['acc'] <= x + 0.2)].shape[0] for x in steps[1:]])
                final_data = DataFrame({'acc': new_arr, 'cell_percentage': [x / total_num for x in acc]})
                print(ggplot(data=final_data,
                             mapping=aes(x='acc', y='cell_percentage')) + \
                      geom_bar(stat="identity") +
                      ggtitle(os.path.basename(file2)) +
                      labs(x='Accuracy', y='Cell percentage') +
                      theme_classic())
        return df


    @staticmethod
    def plot_fragments(files: List[str], concat = List[int]):
        """
        Printing the fragments graphs
        :return: None if there is an error, and the DataFrame representing the fragments data.
        """
        df = decoder.get_acc_df_for_graph_frag(files)
        df = df[df["concatenated_cells"].isin(concat)]

        for pop in df.population.unique():
            df2 = df[df['population'] == pop]
            print(ggplot(data=df2,
                         mapping=aes(x='time', y='acc', group=1)) +
                  geom_line(color='red') +
                  geom_point() + facet_wrap('~concatenated_cells') +
                  ggtitle(pop) +
                  theme_classic() +
                  geom_errorbar(mapping=aes(x="time", ymin='acc-std', ymax='acc+std')))
        return df

    @staticmethod
    def help():
        with open("essentials/graphs_docs", 'r') as info_file:
            for line in info_file.readlines():
                print(line)

    @staticmethod
    def plot_acurracy_comparision(one: str, two: str):
        try:
            df1 = decoder.get_population_one_cell_data_frame(one)
            df2 = decoder.get_population_one_cell_data_frame(two)
        except:
            print("input is invalid: one (or both) of the files is not ok")
            exit(0)
        df1.rename(columns={"acc": "acc1"}, inplace=True)
        df2.rename(columns={"acc": "acc2"}, inplace=True)
        final_df = pd.merge(df1, df2, how ='inner', on =['cell_name'])
        if final_df.shape[0] == 0:
            print("no matching cells")
            exit(0)
        print(ggplot(data=final_df,
                     mapping=aes(x="acc1", y="acc2",color="cell_name")) + \
        geom_point(alpha=0.8) + \
              geom_text(aes(label="cell_name"), fontweight="5") +\
        labs(x=decoder.get_full_name(one) + ' Accuracy', y=decoder.get_full_name(two) + ',Accuracy') + \
              scale_x_continuous(breaks=np.arange(0,  1, 0.05)) + \
              scale_y_continuous(breaks=np.arange(0, 1, 0.05))
        )
        return final_df

