import tkinter as tk
import tkinter.messagebox
import pandas as pd 
import matplotlib.pyplot as plt
from IPython.display import clear_output
from datetime import datetime

# Check the functionalities of smus VAR1,VAR2 and VARD
def check_sweep_func(smus:list,func:str):
    for i, smu in enumerate(smus):
        if smu["func"] == func:
            return True
    return False

# Check if there is a pulsed smu for sweep smu
def check_sweep_pulse(smus:list):
    for smu in smus:
        if "PULSE" in smu["mode"]:
            return True:
    return False

# Check if there any constant smus and return their numbers
def check_sweep_cons(smus:list):
    cons_smu_numbers = []
    for i,smu in enumerate(smus):
        if smu['func']=='CONS' and smu['mode']!='COMM': # Non Grounded SMUs
            cons_smu_numbers.append(i+1) # for the actual number of smus

    return cons_smu_numbers

# Setup the axes in tool
def setup_axes(axes_info:list,device):
    axes_plot = ['X','Y1','Y2']
    for ax_plot,ax_info in zip(axes_plot,axes_info):
        if ax_plot == 'Y2' and ax_info['name'] == "": # Y2 axis can be empty
            pass
        else:
            device.display_variable(ax_plot,ax_info['name'])
            device.axis_scale(ax_plot,ax_info['scale'])
            device.display_variable_min_max(ax_plot,'MIN',ax_info['min'])
            device.display_variable_min_max(ax_plot,'MAX',ax_info['max'])


# Setup the variables to be saved
def save_variables(axes,variables,device):
    # condition number one: the plotted variables need to be saved in the file
    # Sticter policy with exceptions

    # Retrieve the names of the variables
    variable_names =[]
    for variable in variables:
        variable_names.append(variable['name'])

    # Retrieve the axes names (variable)
    axes_names=[]
    for i,ax in enumerate(axes):
        if i != 2 and ax['name']!="" # Y2 axis can be left empty
            axes_names.append(ax['name'])

    # Now Check if axes names are in the variable names
    for ax_name in axes_names:
        if ax_name not in variable_names:
            raise Exception("Plotted Variables should be saved!")

    # Now save the variables
    variable_names =[]
    for variable in variables:
        variable_names.append(variable['name'])

    # Send the command to tool
    device.variables_to_save(variable_names)

    # Now this should work    
    
def error_box(information):
    #open dialog and hide the main window
    root = tk.Tk()
    root.withdraw()
    root.lift() #show window above all other applications

    root.attributes("-topmost", True)#window stays above all other applications

    #display meaagebox
    tkinter.messagebox.showerror(message=information)
    root.destroy()

def information_box(information):
    #open dialog and hide the main window
    root = tk.Tk()
    root.withdraw()
    root.lift() #show window above all other applications

    root.attributes("-topmost", True)#window stays above all other applications

    #display meaagebox
    tkinter.messagebox.showinfo(message=information)
    root.destroy()

# We plot results: but we will play with the axes!
def plot_results(values,device):
    
    # Get the names of the plotted variables
    x_var = device.get_axis_variable('X')
    y1_var = device.get_axis_variable('Y1')
    y2_var = device.get_axis_variable('Y2') # we will check for the empty

    # Get the scales of the plotted variables
    x_scale = device.get_axis_scale('X') # we will check the response too
    y1_scale = device.get_axis_scale('Y1')
    y2_scale = device.get_axis_scale('Y2')

    # Find the values that will be plotted
    for key, results in value.items():
        if x_var in key: # check if the substring is contained
            x_values = results.copy() # This is a list
            x_label = key
        elif y1_var in key:
            y1_values = results.copy()
            y1_label = key
        elif y2_var in key and y2_var != None:
            y2_values = results.copy()
            y2_label = key

    # Now lets do the plot
    fig,ax1 = plt.subplots()

    ax1.set_xlabel(x_label)
    ax1.set_ylabel(y1_label,color = 'y') # Yellow Color
    ax1.set_xscale(x_scale)
    ax1.set_yscale(y1_scale)

    ax1.scatter(x_values,y1_values,color='y')
    ax1.tick_params(axis ='y', labelcolor ='y',which='both')

    if y2_var!= None:
        # Adding Twin Axes # Blue color
        ax2 = ax1.twinx()

        ax2.set_ylabel(y2_label,color = 'b')
        ax2.set_yscale(y2_scale)

        ax2.scatter(x_values,y2_values,color='b')
        ax2.tick_params(axis ='y', labelcolor ='b',which='both')

    display(fig)
    # The checks will be corrected later


def create_file(filename):
    root = tk.Tk()
    root.withdraw()
    root.lift() #show window above all other applications

    root.attributes("-topmost", True)#window stays above all other applications

    file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =filename)

    #check if the file path is correct(.txt)
    while file.endswith(".txt") == False:
        #open again filedialog with error message box
        tk.messagebox.showerror(message='invalid filename!')
        file = filedialog.asksaveasfilename(defaultextension=".txt", filetypes=[("Text files","*.txt")],title = "save results path",initialfile =filename)
    root.destroy()
    return file

# sampling help functions

def check_cons_smu_samp(smus:list):
    cons_smu_numbers = []
    for i,smu in enumerate(smus):
        if smu['mode']!='COMM': # Non Grounded SMUs
            cons_smu_numbers.append(i+1) # for the actual number of smus

    return cons_smu_numbers