## this module contains yaml generator
## it is used to generate yaml files for project settings
## it automatically generates GUI based on the yaml file
## it is still in development

import tkinter as tk
from tkinter import filedialog, messagebox
import yaml
import os


def clear_frame(frame):
    for widget in frame.winfo_children():
        widget.destroy()


def create_widgets(dictionary, frame, widget_refs):
    clear_frame(frame)
    widget_refs.clear()
    row = 0
    for key, value in dictionary.items():
        label = tk.Label(frame, text=key)
        label.grid(row=row, column=0, sticky="ew", padx=10, pady=5)

        if isinstance(value, bool):
            var = tk.BooleanVar(value=value)
            checkbox = tk.Checkbutton(frame, text=key, variable=var)
            checkbox.grid(row=row, column=1, sticky="ew")
            widget_refs[key] = var
        elif isinstance(value, int):
            entry = tk.Entry(frame)
            entry.insert(0, str(value))
            entry.grid(row=row, column=1, sticky="ew")
            widget_refs[key] = entry
        elif isinstance(value, str):
            entry = tk.Entry(frame)
            entry.insert(0, value)
            entry.grid(row=row, column=1, sticky="ew")
            widget_refs[key] = entry

            normalized_path = os.path.abspath(value)

            if os.path.isfile(normalized_path):

                browse_button = tk.Button(
                    frame, text="Browse", command=lambda e=entry: browse_path(e)
                )
                browse_button.grid(row=row, column=2, sticky="ew")
            elif os.path.isdir(normalized_path):
                browse_button = tk.Button(
                    frame, text="Browse", command=lambda e=entry: browse_folder(e)
                )
                browse_button.grid(row=row, column=2, sticky="ew")
            else:
                if any(char in value for char in "/\\"):
                    browse_button = tk.Button(
                        frame, text="Browse", command=lambda e=entry: browse_path(e)
                    )
                    browse_button.grid(row=row, column=2, sticky="ew")
                else:
                    pass

        row += 1


def browse_path(entry_widget):
    path = filedialog.asksaveasfilename()
    entry_widget.delete(0, tk.END)
    entry_widget.insert(0, path)


def browse_folder(entry_widget):
    path = filedialog.askdirectory()
    entry_widget.delete(0, tk.END)
    entry_widget.insert(0, path)


def save_config(widget_refs):
    updated_data = {}
    for key, widget in widget_refs.items():
        if isinstance(widget, tk.BooleanVar):
            updated_data[key] = widget.get()
        elif isinstance(widget, tk.Entry):
            updated_data[key] = widget.get()

    apath = filedialog.asksaveasfilename(
        defaultextension=".yaml", filetypes=[("YAML files", "*.yaml")]
    )
    with open(apath, "w") as file:
        yaml.dump(updated_data, file, sort_keys=False)

    messagebox.showinfo("Save Configuration", "Configuration saved to YAML file")


def load_config(frame, widget_refs):
    apath = filedialog.askopenfilename(filetypes=[("YAML files", "*.yaml")])
    try:
        with open(apath, "r") as file:
            data = yaml.safe_load(file)
            create_widgets(data, frame, widget_refs)
        messagebox.showinfo("Load Configuration", "Configuration loaded successfully")
    except FileNotFoundError:
        messagebox.showinfo(
            "Load Configuration", "Configuration file not found. Using defaults."
        )


def main():
    root = tk.Tk()
    root.title("Dynamic GUI")
    root.geometry("600x400")

    canvas = tk.Canvas(root)
    scrollbar = tk.Scrollbar(root, orient="vertical", command=canvas.yview)
    scrollable_frame = tk.Frame(canvas)

    scrollable_frame.bind(
        "<Configure>", lambda e: canvas.configure(scrollregion=canvas.bbox("all"))
    )

    canvas.create_window((0, 0), window=scrollable_frame, anchor="nw")
    canvas.configure(yscrollcommand=scrollbar.set)

    canvas.grid(row=0, column=0, sticky="nsew")
    scrollbar.grid(row=0, column=1, sticky="ns")

    root.grid_columnconfigure(0, weight=1)
    root.grid_rowconfigure(0, weight=1)

    widget_refs = {}

    project_name_var = "demo"
    project_description_var = "This is example description of a project"
    project_path_var = "/folder/for/project/"
    input_data_var = "folder/file.csv"
    output_path_full_var = "folder/file.csv"
    output_path_only_hyper_hypo_var = "folder/file.csv"
    output_path_hyper_hypo_indeter_var = "folder/file.csv"
    output_path_indeter_indeter_var = "folder/file.csv"
    group_divide_var = 72
    separator_var = ","
    heatmap_var = "### heatmaps settings"
    heatmap_src_var = "hh"
    heatmap_sep_src_var = ","
    heatmap_save_var = True
    heatmap_show_var = False
    heatmap_confidence_thresholds_var = None
    heatmap_sep_samples_var = False
    heatmap_cmap_var = "seismic"
    heatmap_full_output_path_var = None
    heatmap_output_folder_var = None
    heatmap_width_var = 45
    heatmap_height_var = 25
    heatmap_group_divide_var = True
    heatmap_group_divide_width_var = 8
    heatmap_group_divide_color_var = "pink"
    heatmap_title_fontsize_var = 64
    clustermap_var = "### hierach. clustering settings"
    cluster_src_var = "hhi"
    cluster_sep_src_var = ""
    cluster_save_var = "True"
    cluster_show_var = "False"
    cluster_confidence_thresholds_var = None
    cluster_sep_samples_var = False
    cluster_cmap_var = "seismic"
    cluster_full_output_path_var = None
    cluster_output_folder_var = None
    cluster_width_var = 45
    cluster_height_var = 22
    cluster_title_fontsize_var = 64
    cluster_row_var = True
    pca2d_src_var = "hh"
    pca2d_src_sep_var = ","
    pca2d_confidence_thresholds_var = None
    paths_src_var = "hh"
    paths_src_sep_var = ","
    paths_depth_var = 3
    paths_confidence_thresholds_var = None
    paths_show_if_true_var = False
    paths_show_if_var = ""
    paths_save_var = True
    annotation_dataset_path_var = "folder/file.csv"
    annotation_dataset_skiprows_var = 7
    annotation_dataset_sep_var = ","
    annotation_dataset_USC_RefGene_Name_colname_var = "UCSC_RefGene_Name"
    biogrid_dataset_path_var = "folder/file.csv"
    biogrid_dataset_skiprows_var = 35
    biogrid_dataset_sep_var = "\t"
    biogrid_dataset_index_col_var = 2
    cluster_method_var = "ward"
    pca2d_show_var = False
    pca2d_save_var = True
    pca3d_src_var = "hh"
    pca3d_src_sep_var = ","
    pca3d_confidence_thresholds_var = ""
    pca3d_show_var = False
    pca3d_save_var = True

    data = {
        "project_name": project_name_var,
        "project_description": project_description_var,
        "project_path": project_path_var,
        "input_data": input_data_var,
        "output_path_full": output_path_full_var,
        "output_path_only_hyper_hypo": output_path_only_hyper_hypo_var,
        "output_path_hyper_hypo_indeter": output_path_hyper_hypo_indeter_var,
        "output_path_indeter_indeter": output_path_indeter_indeter_var,
        "group_divide": group_divide_var,
        "separator": separator_var,
        "heatmap": heatmap_var,
        "heatmap_src": heatmap_src_var,
        "heatmap_sep_src": heatmap_sep_src_var,
        "heatmap_save": heatmap_save_var,
        "heatmap_show": heatmap_show_var,
        "heatmap_confidence_thresholds": heatmap_confidence_thresholds_var,
        "heatmap_sep_samples": heatmap_sep_samples_var,
        "heatmap_cmap": heatmap_cmap_var,
        "heatmap_full_output_path": heatmap_full_output_path_var,
        "heatmap_output_folder": heatmap_output_folder_var,
        "heatmap_width": heatmap_width_var,
        "heatmap_height": heatmap_height_var,
        "heatmap_group_divide": heatmap_group_divide_var,
        "heatmap_group_divide_width": heatmap_group_divide_width_var,
        "heatmap_group_divide_color": heatmap_group_divide_color_var,
        "heatmap_title_fontsize": heatmap_title_fontsize_var,
        "clustermap": clustermap_var,
        "cluster_src": cluster_src_var,
        "cluster_sep_src": cluster_sep_src_var,
        "cluster_save": cluster_save_var,
        "cluster_show": cluster_show_var,
        "cluster_confidence_thresholds": cluster_confidence_thresholds_var,
        "cluster_sep_samples": cluster_sep_samples_var,
        "cluster_cmap": cluster_cmap_var,
        "cluster_full_output_path": cluster_full_output_path_var,
        "cluster_output_folder": cluster_output_folder_var,
        "cluster_width": cluster_width_var,
        "cluster_height": cluster_height_var,
        "cluster_title_fontsize": cluster_title_fontsize_var,
        "cluster_row": cluster_row_var,
        "pca2d_src": pca2d_src_var,
        "pca2d_src_sep": pca2d_src_sep_var,
        "pca2d_confidence_thresholds": pca2d_confidence_thresholds_var,
        "paths_src": paths_src_var,
        "paths_src_sep": paths_src_sep_var,
        "paths_depth": paths_depth_var,
        "paths_confidence_thresholds": paths_confidence_thresholds_var,
        "paths_show_if_true": paths_show_if_true_var,
        "paths_show_if": paths_show_if_var,
        "paths_save": paths_save_var,
        "annotation_dataset_path": annotation_dataset_path_var,
        "annotation_dataset_skiprows": annotation_dataset_skiprows_var,
        "annotation_dataset_sep": annotation_dataset_sep_var,
        "annotation_dataset_USC_RefGene_Name_colname": annotation_dataset_USC_RefGene_Name_colname_var,
        "biogrid_dataset_path": biogrid_dataset_path_var,
        "biogrid_dataset_skiprows": biogrid_dataset_skiprows_var,
        "biogrid_dataset_sep": biogrid_dataset_sep_var,
        "biogrid_dataset_index_col": biogrid_dataset_index_col_var,
        "cluster_method": cluster_method_var,
        "pca2d_show": pca2d_show_var,
        "pca2d_save": pca2d_save_var,
        "pca3d_src": pca3d_src_var,
        "pca3d_src_sep": pca3d_src_sep_var,
        "pca3d_confidence_thresholds": pca3d_confidence_thresholds_var,
        "pca3d_show": pca3d_show_var,
        "pca3d_save": pca3d_save_var,
    }

    create_widgets(data, scrollable_frame, widget_refs)

    save_button = tk.Button(
        root, text="Save Configuration", command=lambda: save_config(widget_refs)
    )
    save_button.grid(row=1, column=0, sticky="ew", pady=10)

    load_button = tk.Button(
        root,
        text="Load Configuration",
        command=lambda: load_config(scrollable_frame, widget_refs),
    )
    load_button.grid(row=1, column=1, sticky="ew", pady=10)

    root.mainloop()


if __name__ == "__main__":
    main()
