# The code for changing pages was derived from: http://stackoverflow.com/questions/7546050/switch-between-two-frames-in-tkinter
# License: http://creativecommons.org/licenses/by-sa/3.0/	

from database import Table
from analogPressure.sdpArray import SdpArray
from analogPressure.mcp3008 import MCP3008
from digitalPressure.sdp610Array import Spd610Array
from wirelessLoadCell.loadCells import LoadCells
from motorController.pwmOutput import PWM
from motorController.pidController import PID
from ui import *

import tkinter as tk
import tk_tools
from tkinter import filedialog
import time
import numpy as np


class Main(tk.Tk, Table):
  def __init__(self, *args, **kwargs):
    print('initializing window...')
    tk.Tk.__init__(self, *args, **kwargs)
    tk.Tk.wm_title(self, "Windkanal-Tool")

    #early response to user
    self.update_idletasks()

    print('initializing sensors...')
    self.adc = MCP3008(0,0)
    self.pressureSensors = Spd610Array()
    self.forceSensors = LoadCells()
    self.forceSensors.start()
    self.motorController = PWM(32)
    self.pid = PID(100/22, 5, 1)
    self.pid.setWindup(1)
    
    print('initializing database...')
    Table.__init__(self, 
    ["windspeed", "set_value", "motor_pwm"] + 
    ["pressure_{}".format(i) for i in range(8)] + 
    ["adc_{}".format(i) for i in range(1)] + 
    ["force_X_sum", "force_Y_sum", "force_Z_sum"] +
    ["force_X_1", "force_Y_1", "force_Z_1"] +
    ["force_X_2", "force_Y_2", "force_Z_2"] + 
    ["force_X_3", "force_Y_3", "force_Z_3"])


    print('initializing GUI...')
    self.menubar = tk.Menu(self)
 
    self.frameVar = tk.StringVar()
    self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_1', command=self.show_frame, label="Bedienelemente")
    self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_2', command=self.show_frame, label="Kräfte")
    self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_3', command=self.show_frame, label="Druck")
    self.menubar.add_radiobutton(indicatoron=0, variable=self.frameVar, value='Page_4', command=self.show_frame, label="Einstellungen")

    self.menubar.add_command(state=tk.DISABLED, label="          ")

    self.motorEnabled = tk.IntVar()
    self.menubar.add_checkbutton(indicatoron=0, variable=self.motorEnabled, background='#dd5252', label="Motor freischalten", command=lambda: 
        self.menubar.entryconfigure("Motor freischalten", background='#dd5252' if self.motorEnabled.get() == 0 else 'green'))
    self.motorEnabled.set(0)

    self.menubar.add_command(state=tk.DISABLED, label="          ")

    self.menubar.add_command(label="Messwerte speichern", command = self.save_dialog)
    self.menubar.add_command(label='Messwerte löschen', command=self.reset)

    self.menubar.add_command(state=tk.DISABLED, label="          ")

    self.menubar.add_command(label="Beenden", foreground="red", command=self.stop)

    tk.Tk.config(self, menu=self.menubar)

    container = tk.Frame(self)
    container.pack(side="top", fill="both", expand = True)
    container.grid_rowconfigure(0, weight=1)
    container.grid_columnconfigure(0, weight=1)

    self.frames = {}

    for F in (Page_1, Page_2, Page_3, Page_4):

      frame = F(container, self)

      self.frames[F.__name__] = frame

      frame.grid(row=0, column=0, sticky="nsew")

    self.frameVar.set('Page_1')
    self.show_frame()

    print('program ready!')

    self.intervalDelay = 300 # ms
    self.interval()

  def show_frame(self):
    self.frames[self.frameVar.get()].tkraise()

  def popupmsg(self, msg=""):
      popup = tk.Toplevel(self.master)
      popup.wm_title("Error!")
      label = tk.Label(popup, text=msg, font=LARGE_FONT)
      label.pack(side="top", fill="x", pady=10)
      b1 = tk.Button(popup, text="Okay", command=popup.destroy)
      b1.pack()
  
  def save_dialog(self):
    f = filedialog.asksaveasfile(mode='w+', defaultextension=".csv")
    if f is None:
      return
    self.saveAsCsv(f)
    f.close()

  def interval(self):
    self.after(self.intervalDelay, self.interval)
    start = time.time()

    setValue = self.frames['Page_1'].speedSlider.get()
    self.pid.setInput(setValue)

    adcValue = self.adc.getVoltage(0)
    windSpeed = adcValue * 5
    pwmValue = self.pid.update(windSpeed)
    
    if self.motorEnabled.get() == 0:
      self.pid.clear()
      pwmValue = 0
    elif pwmValue > 100:
      pwmValue = 100
    elif pwmValue < 0:
      pwmValue = 0

    self.motorController.setDutyCycle(pwmValue)

    i2cValues = self.pressureSensors.getValues()
    btValues = self.forceSensors.getForces()

    self.addRow(
      [windSpeed, setValue, pwmValue] + 
      i2cValues +
      [adcValue] +
      list(np.sum(btValues, axis = 0, initial=0)) +
      list(btValues.flatten())
    )
    print("sensors: {:8.3f} ms".format((time.time() - start)*1000))

    start = time.time()
    for frame in self.frames:
      self.frames[frame].update(frame == self.frameVar.get())

    print("draw:    {:8.3f} ms".format((time.time() - start)*1000))
    
  def stop(self):
    self.forceSensors.stop()
    self.motorEnabled.set(0)
    self.motorController.setDutyCycle(0)
    self.adc.close()
    self.quit()