import time
import queue

import tkinter as tk
import numpy as np

from gui.popup import CalibrationPopUp
from gui.graph import Graph
from gui.logScreen import LogScreen
import logHandler


class MainWindow(tk.Frame):
  def __init__(self, root, ac_sensor, ac_queue, ac_cal_state, conf):
    self.root = root
    self.popup = None
    self.log_window = None
    self.ac_cal_state = ac_cal_state
    self.ac_sensor = ac_sensor
    self.ac_queue = ac_queue
    self.log_handler = logHandler.get_log_handler()
    self.conf = conf

    tk.Frame.__init__(self, root)
    # data plot at left side
    self.graph = Graph(self)
    self.graph.pack(fill=tk.BOTH, side=tk.LEFT, expand=True)
    # frame at right side
    self.controls = tk.Frame(self, borderwidth=4)
    self.controls.pack(fill=tk.BOTH, side=tk.RIGHT)
    self.controlsUpdateTime = 0

    self.ac_dro_val_sums = np.ndarray((4), dtype=np.float)
    self.ac_dro_val_count = 0
    self.ac_dro_x = tk.StringVar()
    self.ac_dro_y = tk.StringVar()
    self.ac_dro_t1 = tk.StringVar()
    self.ac_dro_t2 = tk.StringVar()
    self.ac_label = tk.Label(self.controls, text="Acoustic Sensor", anchor="c", font=("Helvatica", 10, 'bold'))
    self.ac_label.pack(side="top", fill="both", expand=False)
    tk.Label(self.controls, textvariable=self.ac_dro_x, anchor="nw").pack(side="top", fill="both", expand=False)
    tk.Label(self.controls, textvariable=self.ac_dro_y, anchor="nw").pack(side="top", fill="both", expand=False)
    tk.Label(self.controls, textvariable=self.ac_dro_t1, anchor="nw").pack(side="top", fill="both", expand=False)
    tk.Label(self.controls, textvariable=self.ac_dro_t2, anchor="nw").pack(side="top", fill="both", expand=False)

    quit_button = tk.Button(self.controls, text="Quit", command=self.root.destroy, height=2, foreground="red")
    quit_button.pack(side="bottom", fill="both")

    calibrate_button = tk.Button(self.controls, text="Calibrate", command=self.calibrate, height=4)
    calibrate_button.pack(side="bottom", fill="both")

    clear_button = tk.Button(self.controls, text="Clear graph", command=self.graph.clear, height=4)
    clear_button.pack(side="bottom", fill="both")

    logscreen_button = tk.Button(self.controls, text="Log", command=self.open_log, height=4)
    logscreen_button.pack(side="bottom", fill="both")

  def update(self):
    if not self.root.winfo_exists():
      return

    ac_positions = []
    # aggregate measurements
    while self.ac_queue.qsize() > 0:
      name, data = self.ac_queue.get()
      if name == "data":
        ac_positions.append(data[0:2])
        self.ac_dro_val_sums += data
        self.ac_dro_val_count += 1
    
    # graph shows all values as a line
    self.graph.update([ac_positions])

    # update status color
    if self.ac_sensor.dummyActive:
      self.ac_label.config(fg="white", bg="red")
    elif len(ac_positions) > 0:
      self.ac_label.config(fg="white", bg="green")
    else:
      self.ac_label.config(fg="black", bg="yellow")

    # readouts will only be updated so often
    if self.controlsUpdateTime + 0.4 < time.time():
      self.controlsUpdateTime = time.time()
      # they display the average of all values
      if self.ac_dro_val_count > 0:
        self.ac_dro_val_sums /= self.ac_dro_val_count
      else:
        self.ac_dro_val_sums.fill(0)

      self.ac_dro_x.set("X: {:.1f} mm".format(self.ac_dro_val_sums[0]))
      self.ac_dro_y.set("Y: {:.1f} mm".format(self.ac_dro_val_sums[1]))
      self.ac_dro_t1.set("t1: {:.3f} ms".format(self.ac_dro_val_sums[2]/1000))
      self.ac_dro_t2.set("t2: {:.3f} ms".format(self.ac_dro_val_sums[3]/1000))

      self.ac_dro_val_sums.fill(0)
      self.ac_dro_val_count = 0

    if self.popup:
      self.popup.update()
    
    if self.log_window:
      self.log_window.update()

    self.root.after(30, self.update)

  def calibrate(self):
    self.ac_sensor.start_calibration()
    if not self.popup or not self.pu_root.winfo_exists():
      # create new window
      self.pu_root = tk.Toplevel(self.root)
      self.pu_root.wm_transient(self.root)
      self.pu_root.wm_title("Calibration")
      # make it centered
      x = (self.pu_root.winfo_screenwidth()  - 500) / 2
      y = (self.pu_root.winfo_screenheight() - 200) / 2
      self.pu_root.geometry(f'500x200+{int(x)}+{int(y)}')
      # deactivate mainWindow
      self.pu_root.grab_set()
      self.popup = CalibrationPopUp(self.pu_root, self.ac_cal_state, self.conf)
      self.popup.pack(side="top", fill="both", expand=True)

  def open_log(self):
    #create new window
    self.log_root = tk.Toplevel(self.root)
    self.log_root.wm_transient(self.root)
    self.log_root.wm_title("Logs")
    #center
    x = (self.log_root.winfo_screenwidth()  - 780) / 2
    y = (self.log_root.winfo_screenheight() - 400) / 2
    self.log_root.geometry(f'780x400+{int(x)}+{int(y)}')
    # deactivate mainWindow
    self.log_root.grab_set()
    self.log_window = LogScreen(self.log_root)
    self.log_window.pack(side="top", fill="both", expand=True)

