import CTMeth
from CTMeth.neural.training_settings import read_settings
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import os
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA


def pca3d(params):
    project_name = params["project_name"]
    sep = ","
    src = params["pca3d_src"]
    # src="hhi"
    if src == "hh":
        input_data_path = params["output_path_only_hyper_hypo"]
    elif src == "full":
        input_data_path = params["output_path_full"]
    elif src == "hhi":
        input_data_path = params["output_path_hyper_hypo_indeter"]
    elif src == "ii":
        input_data_path = params["output_path_indeter_indeter"]
    else:
        input_data_path = src
        sep = params["pca3d_src_sep"]

    df = pd.read_csv(input_data_path, index_col=0)
    group_divide = params["group_divide"]

    input_data = pd.read_csv(input_data_path, index_col=0, sep=sep)
    sortby = input_data.columns[5]

    input_data_sorted = input_data.sort_values(by=sortby, ascending=False)

    confidence_array = params["pca3d_confidence_thresholds"]
    if not isinstance(confidence_array, list):
        quantiles = input_data_sorted.iloc[:, 5].quantile([0, 0.50, 0.75, 0.95])
        confidence_array = quantiles.values

    for n in confidence_array:
        cpgs_count = len(input_data_sorted)
        title = f"PCA3D project: {project_name}, src: {src}, conf {n}"
        confidence_threshold = n
        input_data_sorted = input_data_sorted[
            input_data_sorted[sortby] >= confidence_threshold
        ]

        df3 = input_data_sorted.iloc[:, 6:]
        labels = df3.columns.values
        df4 = df3.transpose()
        df4.insert(len(df4.columns), "target", 1)
        df4.target = df4.index
        df4.head()

        features = df4.columns[:-1]
        x = df4.loc[:, features].values
        y = df4.loc[:, ["target"]].values
        targets = df4.target
        features
        try:
            x = StandardScaler().fit_transform(x)

            pca = PCA(n_components=3, svd_solver="full")
            principalComponents = pca.fit_transform(x)
            principalDf = pd.DataFrame(
                data=principalComponents,
                columns=[
                    "principal component 1",
                    "principal component 2",
                    "principal componet 3",
                ],
            )

            df5 = df4["target"]
            df5 = df5.reset_index(drop=True)

            finalDf = pd.concat([principalDf, df5], axis=1)
            pca_explain = pca.explained_variance_ratio_

            for ii in range(0, 360, 60):
                line1 = f"PCA3D project: {project_name}, \n src: {src}, \nconf {round(confidence_threshold,2)}"
                line2 = f"PC1 {pca_explain[0]} PC2 {pca_explain[1]} \nPC2 {pca_explain[2]} \nPCs sum: {round(sum(pca_explain),2)} , cpgs_count {cpgs_count}"
                title = "".join([line1, "\n", line2])
                colors = []
                for n in range(group_divide):
                    colors.append("red")
                for n in range(group_divide, len(labels)):
                    colors.append("blue")

                from mpl_toolkits.mplot3d import proj3d

                # ToDo hover over points to get labels

                fig = plt.figure()
                ax = fig.add_subplot(projection="3d")
                ax.set_title(title)

                xs = finalDf.iloc[:, 0]
                ys = finalDf.iloc[:, 1]
                zs = finalDf.iloc[:, 2]
                ax.set_xlabel("PC1 Label")
                ax.set_ylabel("PC2 Label")
                ax.set_zlabel("PC3 Label")

                buldog = ax.scatter(xs, ys, zs, color=colors, picker=True)
                ax.view_init(elev=20.0, azim=ii)
                if params["pca3d_show"] == True:
                    if ii < 1:
                        plt.show()
                if params["pca3d_save"] == True:
                    try:
                        pca_output_folder = params["pca3d_output_folder"]
                    except KeyError:
                        print("pca output folder not specified")
                        pca_output_folder = params["project_path"]
                    if not isinstance(pca_output_folder, str):
                        pca_output_folder = params["project_path"]
                    else:
                        if len(pca_output_folder) < 1:
                            pca_output_folder = params["project_path"]
                    savefigpth = pca_output_folder
                    basename = os.path.basename(input_data_path)[:-4]
                    imagename = f"pca3d_{basename}-conf{round(confidence_threshold,2)}-src-{src}-azi{ii}.png"
                    savefigpth = os.path.join(savefigpth, imagename)
                    print(f"saving to : {savefigpth}")
                    plt.savefig(savefigpth, bbox_inches="tight")
                plt.close()

        except:
            import traceback

            print(traceback.format_exc())
            pass
