import Tkinter  
import LumexData
import tkFileDialog
import tkMessageBox
import os

class Window(object):
 
    #Initialize a window containig a menu with different options and a textwidget for displaying the data
    def __init__(self, master):
        
        self.fittype = "lin"
        self.averaged = 0
        self.av_dates = 0
        self.errors = 0
        self.parameter = [1,1]
        self.fitparams = [0]
        self.flag = []
        self.fit = False
        self.__f = None
        self.__master = master
        self.calibrationsfile = None
        
        menu = Tkinter.Menu(self.__master)
        self.__master.config(menu=menu)
        frame = Tkinter.Frame(self.__master)
        frame.pack()

        filemenu = Tkinter.Menu(menu)
        menu.add_cascade(label="File", menu=filemenu)
        filemenu.add_command(label="Import", command=self.__importCalib)
        filemenu.add_command(label="Reload", command=self.__reload)
        filemenu.add_command(label="Clear workspace", command=self.__clear)
        filemenu.add_separator()
        filemenu.add_command(label="Exit", command=frame.quit)

        processingmenu = Tkinter.Menu(menu)
        menu.add_cascade(label="Processing", menu=processingmenu)
        processingmenu.add_command(label="Flagging", command=self.__flagging)
        processingmenu.add_command(label="Averaging", command=self.__averaging)
        processingmenu.add_command(label="Save Time-Concentration", command=self.__storeTimeConc)
        

        plotmenu = Tkinter.Menu(menu)
        menu.add_cascade(label="Plotting", menu=plotmenu)
        plotmenu.add_command(label="Linear fit", command=self.__fitLine)
        plotmenu.add_command(label="Polynomial fit", command=self.__getDegree)
        plotmenu.add_command(label="Trigonometric fit", command=self.__fitTrig)
        plotmenu.add_command(label="Exponential fit", command=self.__fitExp)
        plotmenu.add_command(label="Logarthmic fit", command=self.__fitLog)
        plotmenu.add_command(label="Gaussian fit", command=self.__fitGauss)
        plotmenu.add_command(label="Unfit", command=self.__unfit)
        plotmenu.add_separator()
        plotmenu.add_command(label="Plot", command=self.__readPlotParams)
        plotmenu.add_command(label="Show fitparameter", command=self.__showFitparams)
        
        helpmenu = Tkinter.Menu(menu)
        menu.add_cascade(label="Help", menu=helpmenu)
        helpmenu.add_command(label="Documentation", command=self.__help)
        helpmenu.add_command(label="About", command=self.__about)
 

        
        self.textfield = Tkinter.Text(self.__master, height=10, width=120) #Add a textfield
        self.scrollbar = Tkinter.Scrollbar(self.__master) #Add a scrollbar
        self.scrollbar.pack(side=Tkinter.LEFT, fill=Tkinter.Y)
        self.textfield.pack(side=Tkinter.LEFT, fill=Tkinter.Y)

    #Open a dialog for choosing the calibration file. Display in a textfield and put the options 
    #on the right side
    def __importCalib(self):
        self.__f = tkFileDialog.askopenfile()
        self.calibrationsfile = LumexData.LumexData(filedescriptor=self.__f)

        self.scrollbar.config(command=self.textfield.yview)
        self.textfield.config(yscrollcommand=self.scrollbar.set)
        self.__reload()
        return

    #Calling LumexData.flagging
    def __flagging(self):
        self.calibrationsfile.flagging()
        return

    #Clear the workspace
    def __clear(self):
        self.calibrationsfile = None
        self.parameters = 0
        self.averaged = 0
        self.textfield.delete("1.0", Tkinter.END)
        return

    #Reload the textwidget
    def __reload(self):
        try:
            self.showing.pack_forget()
        except AttributeError:
            pass
        if(self.calibrationsfile.averaged == False):
            self.textfield.delete("1.0", Tkinter.END)
            self.textfield.insert(Tkinter.END, "1. Date\n2. Concentration (ng/m^3)\n3. Temperature (C)\n4. Flag\n")
            self.textfield.insert(Tkinter.END, "-----------------------------------------------\n")
            for i in range(self.calibrationsfile.length()):
                date = self.calibrationsfile.get(i, "date")
                concentration = self.calibrationsfile.get(i, "concentration")
                temperature = self.calibrationsfile.get(i, "temperature")
                flag = self.calibrationsfile.get(i, "flag")
                self.textfield.insert(Tkinter.END, "{}\t|\t{}\t|\t{}\t|\t{}\n".format(date, round(concentration,3), round(temperature,3), flag))
        else:
            self.textfield.delete("1.0", Tkinter.END)
            self.textfield.insert(Tkinter.END, "1. Date\n2. Concentration (ng/m^3)\n3. Standard deviation (ng/m^3)\n4. Number of measurements\n5. Flag\n")
            self.textfield.insert(Tkinter.END, "-----------------------------------------------\n")
            for i in range(self.calibrationsfile.length()):
                date = self.calibrationsfile.get(i, "date")
                concentration = self.calibrationsfile.get(i, "concentration")
                flag = self.calibrationsfile.get(i, "flag")
                standarddeviation = self.calibrationsfile.get(i, "standarddeviation")
                counter = self.calibrationsfile.get(i, "counter")
                self.textfield.insert(Tkinter.END, "{}.{}.{}\t|\t{}\t|\t{}\t|\t{}\t|\t{}\n".format(date.day, date.month, date.year, round(concentration,3), round(standarddeviation,4), counter, flag))
        return

    #Calling LumexData.averaging
    def __averaging(self):
        [self.averaged, self.errors, self.av_dates, self.flag] = self.calibrationsfile.averaging(overwrite=True)
        return

    #Calling LumexData.storeTimeConc
    def __storeTimeConc(self):
        filename = "timeconc.dat"
        self.calibrationsfile.storeTimeConc(filename)
        return 

    #Different wrappermethods for fitting the data
    def __fitLine(self):
        self.__fit("lin", 2, "p_0 * x + p_1")
        return

    def __fitTrig(self):
        self.__fit("trig", 4, "p_0 * cos(2*pi / (p_1*x) + p_2) + p_3*x")
        return 

    def __fitExp(self):
        self.__fit("exp", 5, "p_0 * exp(p_1*x + p_2) * p_3*x + p_4")
        return

    def __fitLog(self):
        self.__fit("log", 4, "p_0 * log(x)/log(p_1) + p_2*x + p_3")
        return

    def __fitGauss(self):
        self.__fit("gauss", 2, "1 / (p_0 * sqrt(2*pi)) * exp(-0.5 * ((x-p_1)/p_0)^2)")
        return

    #Read the fitparameters
    def __fit(self, typ, textfields, fitfunction):
        try:
            self.showing.pack_forget()
        except AttributeError:
            pass
        textoutput = "Fit function\n{}\n".format(fitfunction)
        self.fit = True
        self.fittype = typ
        self.px = [Tkinter.Entry(self.__master) for x in range(textfields)]
        self.textwidget = Tkinter.Label(self.__master, text="Insert initial parameters")
        self.forgetButton = Tkinter.Button(self.__master, text="Cancel", command=self.__forget)
        self.saveButton = Tkinter.Button(self.__master, text="Save", command=self.__save)
        self.fitfunc = Tkinter.Label(self.__master, text=textoutput)
        self.forgetButton.pack(side=Tkinter.BOTTOM)
        self.saveButton.pack(side=Tkinter.BOTTOM)
        for field in self.px:
            field.pack(side=Tkinter.BOTTOM)
        self.textwidget.pack(side=Tkinter.BOTTOM)
        self.fitfunc.pack(side=Tkinter.BOTTOM)
        return

    #Save the fitparameters
    def __save(self):
        self.parameter = []
        for element in self.px:
            self.parameter.append(float(element.get()))
        self.__forget()
        return

    #Clear the window and delete the input widgets for the fitparameters
    def __forget(self):
        self.textwidget.pack_forget()
        for element in self.px:
            element.pack_forget()
        self.saveButton.pack_forget()
        self.forgetButton.pack_forget()
        self.fitfunc.pack_forget()
        return

    #Read the degree for the polynomial fit
    def __getDegree(self):
        self.textwidget = Tkinter.Label(self.__master, text="Insert degree (2 - 6)")
        self.saveButton = Tkinter.Button(self.__master, text="Save", command=self.__saveDegree)
        self.p0 = Tkinter.Entry(self.__master) 
        self.saveButton.pack(side=Tkinter.BOTTOM)
        self.p0.pack(side=Tkinter.BOTTOM)
        self.textwidget.pack(side=Tkinter.BOTTOM)
        return
    
    #Save the degree for the polynomial fit and call self.__fit
    def __saveDegree(self):
        self.degree = int(self.p0.get())
        self.textwidget.pack_forget()
        self.p0.pack_forget()
        self.saveButton.pack_forget()
        self.__fit("poly{}".format(str(self.degree)), self.degree+1, "sum_i=0^n p_i * x^(n-i)")
        return
    
    def __readPlotParams(self):
        f = open("plot.ini", "r")
        content = f.readlines()
        print(int(content[0]))
        if(int(content[0]) > 0):
            self.title=str(content[1].split("=")[1][:-1])
            self.xlabel=str(content[2].split("=")[1][:-1])
            self.ylabel=str(content[3].split("=")[1][:-1])
            self.ran=str(content[4].split("=")[1][:-1])
            self.axessize=int(content[5].split("=")[1])
            self.fontsize=int(content[6].split("=")[1])
            self.markersize=int(content[7].split("=")[1])
            self.colour=str(content[8].split("=")[1][:-1])
            self.markerstyle=str(content[9].split("=")[1][:-1])
            self.__plot()
        else:
            self.titleWidget = Tkinter.Label(self.__master, text="Title")
            self.xlabelWidget = Tkinter.Label(self.__master, text="X-Label")
            self.ylabelWidget = Tkinter.Label(self.__master, text="Y-Label")
            self.ranWidget = Tkinter.Label(self.__master, text="Range")
            self.axessizeWidget = Tkinter.Label(self.__master, text="Axes size")
            self.fontsizeWidget = Tkinter.Label(self.__master, text="Font size")
            self.markersizeWidget = Tkinter.Label(self.__master, text="Marker size")
            self.colourWidget = Tkinter.Label(self.__master, text="Marker colour")
            self.markerstyleWidget = Tkinter.Label(self.__master, text="Marker style")
            self.titleText = Tkinter.Entry(self.__master)
            self.xlabelText = Tkinter.Entry(self.__master)
            self.ylabelText = Tkinter.Entry(self.__master)
            self.ranText = Tkinter.Entry(self.__master)
            self.axessizeText = Tkinter.Entry(self.__master)
            self.fontsizeText = Tkinter.Entry(self.__master)
            self.markersizeText = Tkinter.Entry(self.__master)
            self.colourText = Tkinter.Entry(self.__master)
            self.markerstyleText = Tkinter.Entry(self.__master)
            self.saveSettings = Tkinter.Button(self.__master, text="Save", command=self.__plot)
            self.saveSettings.pack(side=Tkinter.BOTTOM)
            self.markerstyleText.pack(side=Tkinter.BOTTOM)
            self.markerstyleWidget.pack(side=Tkinter.BOTTOM)
            self.colourText.pack(side=Tkinter.BOTTOM)
            self.colourWidget.pack(side=Tkinter.BOTTOM)
            self.markersizeText.pack(side=Tkinter.BOTTOM)
            self.markersizeWidget.pack(side=Tkinter.BOTTOM)
            self.fontsizeText.pack(side=Tkinter.BOTTOM)
            self.fontsizeWidget.pack(side=Tkinter.BOTTOM)
            self.axessizeText.pack(side=Tkinter.BOTTOM)
            self.axessizeWidget.pack(side=Tkinter.BOTTOM)
            self.ranText.pack(side=Tkinter.BOTTOM)
            self.ranWidget.pack(side=Tkinter.BOTTOM)
            self.ylabelText.pack(side=Tkinter.BOTTOM)
            self.ylabelWidget.pack(side=Tkinter.BOTTOM)
            self.xlabelText.pack(side=Tkinter.BOTTOM)
            self.xlabelWidget.pack(side=Tkinter.BOTTOM)
            self.titleText.pack(side=Tkinter.BOTTOM)
            self.titleWidget.pack(side=Tkinter.BOTTOM)
        return

    #Plot the data. If the file plot.ini is empty, ask the user for input different plot options
    def __plot(self):
        try:
            self.title = str(self.titleText.get())
            self.xlabel = str(self.xlabelText.get())
            self.ylabel = str(self.ylabelText.get())
            self.ran = str(self.ranText.get())
            self.axessize = int(self.axessizeText.get())
            self.fontsize = int(self.fontsizeText.get())
            self.markersize = int(self.markersizeText.get())
            self.colour = str(self.colourText.get())
            self.markerstyle = str(self.markerstyleText.get())
            self.saveSettings.pack_forget()
            self.markerstyleText.pack_forget()
            self.markerstyleWidget.pack_forget()
            self.colourText.pack_forget()
            self.colourWidget.pack_forget()
            self.markersizeText.pack_forget()
            self.markersizeWidget.pack_forget()
            self.fontsizeText.pack_forget()
            self.fontsizeWidget.pack_forget()
            self.axessizeText.pack_forget()
            self.axessizeWidget.pack_forget()
            self.ranText.pack_forget()
            self.ranWidget.pack_forget()
            self.ylabelText.pack_forget()
            self.ylabelWidget.pack_forget()
            self.xlabelText.pack_forget()
            self.xlabelWidget.pack_forget()
            self.titleText.pack_forget()
            self.titleWidget.pack_forget()
        except AttributeError:
            pass
        self.calibrationsfile.plotting(title=self.title, xlabel=self.xlabel, ylabel=self.ylabel, ran=self.ran, axessize=self.axessize, fsize=self.fontsize, msize=self.markersize, colour=self.colour, markerstyle=self.markerstyle, typ=self.fittype, parameter=self.parameter, leastsq=self.fit, averaged=self.averaged, errors=self.errors, av_date=self.av_dates, flag=self.flag)
        return

    #Print the fitparameters to the window
    def __showFitparams(self):
        try:
            textoutput = ""
            f = open("fitparams.txt", "r")
            content = f.readlines()
            for element in content:
                textoutput = textoutput + element
            self.showing = Tkinter.Label(self.__master, text=textoutput)
            self.showing.pack(side=Tkinter.BOTTOM)
        except IOError:
            pass

        return

    #Don't display the fitfunction in the next plot
    def __unfit(self):
        self.fit = False
        return

    #Opening Iceweasel with the HTML help
    def __help(self):
        f = open("properties.ini", "r")
        content = f.readlines()
        os.system(content[0])
        f.close()
        return

    def __about(self):
        tkMessageBox.showinfo("About", "LumexData 0.8_rc \nPublished under MIT-Licence")
        return
                             

if __name__ == '__main__':
    root = Tkinter.Tk()
    root.wm_title("LumexData")
    root.geometry("1200x768")
    window = Window(root)
    root.mainloop()
        
        
