import os
import sys
import re
import numpy as np
from numpy import exp, log, log10, sqrt, sin, cos, tan
from importlib import import_module
from matplotlib import pyplot as plt
import tkinter as tk


from tklib.tkapplication import tkApplication
from tklib.tkutils import getarg, getintarg, getfloatarg, pint, pfloat, split_file_path, replace_path, print_line
from tklib.tkfile import tkFile
from tklib.tkparams import tkParams
from tklib.tkvariousdata import tkVariousData
from tklib.tkfilter import tkFilter
from tklib.tksci.tksci import Gaussian, Lorentzian, GaussLorentz
from tklib.tksci.tkmatrix import make_matrix1, make_matrix2, make_matrix3
from tklib.tkgraphic.tkplotevent import tkPlotEvent, RangeSelector
from tklib.tkgraphic.tkplot_pyplot import select_plt, tkPlot_pyplot
from tklib.tkgraphic.tkplot_tkinter import tkPlot_tkinter
from tklib.tkgui.tksimple_gui import tkWidgets, CustomDialog_with_config
#from tklib.tkgui.tksimple_gui import get_window_from_plt, add_widgets, update_variables, show_varibles, CustomDialog_with_config


"""
Split multiple data to multiple files
"""


ProgramName = "XRF fit"


#===================================
# Global variables
#===================================
markers = ['o', 's', '+', 'x', 'D', 'v', '^', '<', '>', '8', 'h', 'H']
colors  = ['black', 'red', 'blue', 'darkgreen', 'darkorange', 'hotpink', 'lightgreen', 'cyan', 'yellow', 'magenta', 'chocolate', 
           'navy', 'slategray', 'olive' ]

figsize         = (8, 6)
fontsize        = 12
legend_fontsize = 8


#=============================
# Treat argments
#=============================
def usage(app = None, cparams = None):
    cparams = app.get_params()
    for s in app.usage_str.split('\n'):
        cmd = 'print({})'.format(s.rstrip())
        eval(cmd)

def initialize(app = None):
    argv, narg   = app.get_argv()
    app.cfg  = tkParams()
    cfg      = app.cfg
    cfg.debug       = 0
    cfg.print_level = 0

    infile  = "KI240409-1-IGZO.txt"

    app.add_argument(opt = "--mode", type = "str", desc = 'mode=[plot_all|peak_search]', defval = 'plot_all', optional = True)

    def_plugin_dir = os.path.join(os.environ["tkprog_X_path"], 'plugin', "filter")
    app.add_argument(opt = "--input_plugin_dir", type = "str", var_name = 'input_plugin_dir',  opt_str = "--input_plugin_dir=dir", 
                    desc = 'input_plugin_dir', defval = def_plugin_dir, optional = False)
    app.add_argument(opt = "--input_plugin_name", type = "str", var_name = 'input_plugin_name',  opt_str = "--input_plugin_name=file_body", 
                    desc = 'input_plugin_name', defval = 'xlsx2xlsx', 
                    optional = False)

    app.add_argument(opt = "--infile", type = "str", var_name = 'infile',  opt_str = "--infile=path", 
                    desc = 'input file path', defval = infile, optional = True)

    return cfg

def update_vars(app = None, cparams = None):
    args_opt, args_idx, args_vars = app.read_args(vars = cparams, check_allowed_args = True, apply_default = True)
    if args_opt is None:
        error_no = args_idx
        error_message = args_vars
        app.terminate("\n\n"
                   +  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!\n"
                   + f"!  {error_message}\n"
                   +  "!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!",
                   usage = app.usage)


def read_file(path, app, cparams):
        module = None
        for i in range(len(modules)):
            name = module_names[i]
            m = modules[i]

            file_type  = m.check_file_type(path, app = app, cparams = cparams)
            print(f"try [{name}] for [{path}]: file_type={file_type}")
            if file_type is not None and 'Error' not in file_type:
                module = m
                module_name = name
                break

        if module is None and 'Error':
            return None, None

        inf = module.read_data(path, app = app, cparams = cparams)

        return module_name, module, inf

def load_input_modules(app, cparams):
    if cparams.input_plugin_name == '':
        cparams.plugin_dir = os.path.join(os.environ['tkprog_X_path'], 'XRF', 'filter')

        print()
        print(f"Load modules from [{cparams.plugin_dir}] (auto judge)")
        module_names, modules = app.load_modules(cparams.plugin_dir, "*.py", target = "read_data", is_print = True)

        for m in modules:
            input_type  = m.get_input_type(app = app, cparams = cparams)
            print(f"  {m.name}: input_type={input_type}")

        module_name, module_input, inf_in = read_file(cparams.infile, app, cparams)
#        print("module_name=", module_name)
        if len(module_name) == 0:
            app.terminate(f"Error in extract_data.extract(): Can not find a module for [{cparams.infile}]", pause = True)

        cparams.in_module_names = [module_name]
        cparams.in_modules      = [module_input]
    else:
        print("")
        print(f"Load input module from {cparams.input_plugin_dir}/{cparams.input_plugin_name}.py")

        filter_in = tkFilter(app = app, cparams = cparams, plugin_dir = cparams.input_plugin_dir, module_file = f"{cparams.input_plugin_name}.py")
        cparams.in_module_names, cparams.in_modules = filter_in.load(target = "read_data", is_print = True)
        print("cparams.in_module_names=", cparams.in_module_names)
        if len(cparams.in_module_names) == 0:
            app.terminate(f"\nError in extract(): Cannot load [{cparams.input_plugin_dir}/{cparams.input_plugin_name}.py]", pause = True)

        print("Read input files:", cparams.infile)
        inf_in = filter_in.read_data(0, cparams.infile, app = app, cparams = cparams, is_print = True)

    return inf_in

def plot(app, cparams, tkplt, fig, axes, inf_in):
    inf_list  = inf_in["meta"]
#    sample    = inf_in.get("sample_name", "")
    labels    = inf_in["labels"]
    data_list = inf_in["data_list"]
    nspectrum = len(data_list)
    ndata     = len(data_list[0])

    for isp in range(nspectrum):
        ax = axes[isp]

        subinf = inf_list[isp]
        x_list, y_list = data_list[isp]
        xmin = x_list[0]
        xmax = x_list[-1]
        print(f"  {subinf['range']}: {subinf['name']} 2Q=[{xmin}, {xmax}]:  wl={subinf['_WL']} A  Xtal={subinf['_Xtal']}")

#        ax.set_title(f"{cparams.infile}")
        ax.tick_params(labelsize = fontsize)
        ax.plot(x_list, y_list, label = subinf['name'])

        ax.set_xlabel(r'2$\theta$', fontsize = fontsize)
        if isp == 0:
            ax.set_ylabel('Intensity', fontsize = fontsize)
        legend = ax.legend(fontsize = legend_fontsize)
        legend.set_draggable(True)

    tkplt.tight_layout()
#    tkinter.mainloop()

def plot_all(app, cparams):
    print()
    print(f"input_plugin: {cparams.input_plugin_dir}/{cparams.input_plugin_name}")
    print(f"input file : {cparams.infile}")

    inf_in = load_input_modules(app, cparams)
    data_list = inf_in["data_list"]
    nspectrum = len(data_list)

    print()
    print("plot")
    tkplt, root, tkpyplot = select_plt(use_tkinter = 1, plt = plt, parent = None, title = "XRF fit")
    fig, axes = tkplt.subplots(1, nspectrum, figsize = figsize, dpi = 100, tight_layout = False)

    plot_event = tkPlotEvent(plt)
#   plot_event.add_stop_button()
#   plot_event.prepare_annotation()
#   plot_event.prepare_popup_menu(fig, parent = root)

    tkplt.create_window(fig)
    tkplt.add_toolbar()

    wg = tkWidgets(parent = tkplt.parent, plt = plt)
    notebook = wg.add_tab()
    page1_frame = wg.add_page(notebook, title = "main")
    page2_frame = wg.add_page(notebook, title = "configure")

    top_frame = tk.Frame(page1_frame) #tkplt.parent)
    top_frame.pack(side = tk.TOP, expand = True, fill = "both")

    left_frame = tk.Frame(top_frame)
    left_frame.pack(side = tk.LEFT, anchor = "n", expand = True, fill = "x")

    canvas_frame = tk.Frame(top_frame)
    canvas = tkplt.add_canvas(fig, parent = canvas_frame)
    canvas_frame.pack(side = tk.LEFT, expand = True, fill = "both")

    def save_figure(fig, outfile = "figure.png"):
        print()
        print(f"Save figure to [{outfile}]")
        fig.savefig(outfile)

    def redraw():
#       self.ax.clear()  # 既存のグラフをクリア
        tkplt.draw()
        canvas.draw()

    tkplt.add_toolbar_button(text = "Save figure", command = lambda: save_figure(fig))
    tkplt.add_toolbar_button(text = "Redraw", command = redraw)

    wg.vars.update(Vg_min = 0, Vg_max = 10, Vd_min = 0, Vd_max = 20)

    def on_click():
#        show_varibles(config)
        wg.update_variables()
        print("clicked", wg.vars.Vg_min, wg.vars.Vg_max, wg.vars.Vd_min, wg.vars.Vd_max)

#    button1 = tk.Button(left_frame, text = "test")#, command = command)
    widgets = [
#            [{"type": "widget", "widget": button1}],
            [{"type": "label", "label": "Vg:", "width": None}, 
             {"type": "entry","varname": "Vg_min", "vartype": "float", "width": 10, "expand": True, "fill": "x"},
             {"type": "label", "label": "-",   "width": None}, 
             {"type": "entry","varname": "Vg_max", "vartype": "float", "width": 10, "expand": True, "fill": "x"},
             {"type": "label", "label": "  ",  "width": None},
            ],
            [{"type": "label", "label": "Vd:", "width": None}, 
             {"type": "entry","varname": "Vd_min", "vartype": "float", "width": 10, "expand": True, "fill": "x"},
             {"type": "label", "label": "-",   "width": None}, 
             {"type": "entry","varname": "Vd_max", "vartype": "float", "width": 10, "expand": True, "fill": "x"},
             {"type": "label", "label": "  ",  "width": None},
            ],
            [{"type": "button", "name": "smoothing", "text": "smoothing", "anchor": "w", "command": on_click}],
            [{"type": "button", "name": "peak_search", "text": "peak search", "anchor": "w", "command": on_click}],
            [{"type": "listbox", "name": "test", "text": "data", "anchor": "w", 
                    "options": ["all", "b"], "sel": 0, "width": 20, "height": 5, "command": on_click}],
            [{"type": "combobox", "name": "test", "text": "data", "anchor": "w", 
                    "options": ["all", "b"], "sel": 0, "width": 20, "height": 5, "command": on_click}],
            [{"type": "checkbox", "varname": "cb", "text": "data", "anchor": "w", "value": True}],
            [{"type": "radiobutton", "varname": "rb", "anchor": "w", 
                    "options": ["all", "b"], "sel": 0}],
            [{"type": "label", "varname": "input_path", "label": "input"}],
            [{"type": "path", "varname": "input_path", "label": "input", "value": "***", 
                    "width": 30,
                    "title": "Choose input file", "command": None}],
            ]

    widgets_frame, config_left_pain = wg.add_widgets(parent = left_frame, widgets = widgets, side = "top", expand = True, fill = "x")

    plot(app, cparams, tkplt, fig, axes, inf_in)
    tkplt.pause(0.1)
    input("Press ENTER to terminate>>")
    
def main():
    app     = tkApplication()
    cfg = initialize(app)
#--infile引数をチェックし、読み込みファイル名を最初に確定する
    cfg.infile = app.check_arg('--infile', defval = None, vartype = 'str')

#cfg.infileからログファイル名を作り、console出力をredirectする
    logfile = app.replace_path(None, template = ["{dirname}", "{filebody}-out.txt"])
    logfile = app.replace_path(cfg.infile)
#    logfile = app.replace_path(cparams.infile, template = ["{dirname}", "{filebody}-out.txt"])
    app.redirect(heading = f"Open logfile [{logfile}]", targets = ["stdout", logfile], mode = 'w')

    app.print_title(f"#  {ProgramName}")

#起動時引数で与えられたパラメータをcfgに設定
    app.update_vars(cfg,apply_default = True)

# cfg.modeで与えられた関数が定義されていれば、呼び出す
    if cfg.mode in globals():
        globals()[cfg.mode](app, cfg)
    else:
        app.terminate("Error in main: Invalide mode [{}]".format(cfg.mode), usage = app.usage, pause = True)

#    app.terminate(pause = True)#usage = usage)


if __name__ == "__main__":
    main()
