import tkinter as tk
import time, math
from PIL import Image, ImageDraw, ImageTk, ImageFont

class Graph(tk.Canvas):
  def __init__(self, root, scale=(-100, 550), **kwargs):
    self.root = root
    tk.Canvas.__init__(self, root, **kwargs)
    self.height = self.winfo_reqheight()
    self.width = self.winfo_reqwidth()
    self.lastPoints = [(0, 0)] * 3
    self.scale = scale
    self.colors = [(100, 255, 100, 255), (255, 100, 100, 255) ,(100, 100, 255, 255)]
    self.font = ImageFont.truetype("gui/SourceSansPro-Semibold.otf", 12)
    self.lineWidth = 1
    
    self.drawBackground()
    self.canvas = self.bg.copy()
    self.image = self.create_image(0, 0, image=None, anchor='nw')

    self.bind("<Configure>", self.on_resize)

  def drawBackground(self):
    self.bg = Image.new('RGB', (self.width, self.height), (0,20,0))
    draw = ImageDraw.Draw(self.bg)

    axes = self.pointToCoord((0, 0))

    # draw x and y axis
    draw.line([(0, axes[1]), (self.width, axes[1])], (60,127,127), self.lineWidth)
    draw.line([(axes[0], 0), (axes[0], self.height)], (60,127,127), self.lineWidth)

    # draw ticks
    for p in range(self.scale[0], self.scale[1], 10**int(math.log10(self.scale[1]-self.scale[0]))):
      tickPosX = self.pointToCoord((p, 0))
      tickPosY = self.pointToCoord((0, p))
      draw.line([(tickPosX[0], tickPosX[1]+self.lineWidth*3), (tickPosX[0], tickPosX[1]-self.lineWidth*3)], (60,127,127), int(self.lineWidth/2))
      draw.line([(tickPosY[0]+self.lineWidth*3, tickPosY[1]), (tickPosY[0]-self.lineWidth*3, tickPosY[1])], (60,127,127), int(self.lineWidth/2))

      draw.text((tickPosX[0]+3, tickPosX[1]+self.lineWidth*4), str(p) + " mm", font=self.font)
      if p != 0:
        draw.text((tickPosY[0]-self.lineWidth*4-35, tickPosY[1]), str(p) + " mm", font=self.font)

  def on_resize(self,event):
    self.width = max(100, event.width-4)
    self.height = max(100, event.height-4)
    self.lineWidth = int(max(min(self.width,self.height) / 100, 1))
    # resize the canvas 
    self.canvas = self.canvas.resize((self.width, self.height))
    self.drawBackground()
    self.canvas = Image.blend(self.canvas, self.bg, 1)

  def pointToCoord(self, point):
    return ((point[0] - self.scale[0]) / (self.scale[1]-self.scale[0]) * self.width, 
      self.height - (point[1] - self.scale[0]) / (self.scale[1]-self.scale[0]) * self.height - 1)

  def update(self, data):
    coord = [[self.pointToCoord(p)] for p in self.lastPoints]

    for i in range(len(data)):
      for point in data[i]:
        coord[i].append(self.pointToCoord(point))

    self.lastPoints = [line[-1] for line in data]

    self.canvas = Image.blend(self.canvas, self.bg, 1/100)
    draw = ImageDraw.Draw(self.canvas)
    for i in range(len(coord)):
      draw.line(coord[i], fill=self.colors[i], width=self.lineWidth+2, joint='curve')

    self.photo = ImageTk.PhotoImage(self.canvas)
    self.itemconfig(self.image, image=self.photo)
