import cv2 as cv
 import numpy as np
 import queue
+import time
 import threading
 import random
+import matplotlib.pyplot as plt
 
 class VideoCapture:
        def __init__(self, device_id, backend):
 
                self.camera = cv.VideoCapture(device_id, backend)
+               self.camera.set(cv.CAP_PROP_BUFFERSIZE, 1)
                self.camera.set(cv.CAP_PROP_FRAME_WIDTH, 1920.0)
                self.camera.set(cv.CAP_PROP_FRAME_HEIGHT, 1080.0)
 
                device_id: int = 0,
                debug: bool = True,
                dummy: bool = False,
+               use_lookup: bool = False,
                use_files: bool = False
        ):
 
                self.match_histograms = False
                self.show_debug = debug
                self.dummy = dummy
+               self.use_lookup = use_lookup
+               self.use_files = use_files
 
-               self.camera = VideoCapture(device_id, cv.CAP_V4L)
+               self.camera = cv.VideoCapture(device_id, cv.CAP_V4L)
 
-               self.camera.set(cv.CAP_PROP_BUFFERSIZE, 38)
+               self.camera.set(cv.CAP_PROP_FPS, 30)
+               self.camera.set(cv.CAP_PROP_BUFFERSIZE, 1)
                self.camera.set(cv.CAP_PROP_FRAME_WIDTH, 1920.0)
                self.camera.set(cv.CAP_PROP_FRAME_HEIGHT, 1080.0)
 
                self.homography = None
-               self.lookup_color = None
-               self.lookup_vingette = None
-               self.lookup_compression = None
+               self.lookup = None
+               self.lookup_compression = 100
                self.last_display = None
                self.last_capture = None
                self.last_recovered = None
 
                else:
                        print("calibration failed")
+                       quit()
+
+               if self.use_file == True:
+                       self.get_lookup()
 
        def get_lookup(
                self
        ) -> None:
 
-               if self.dummy == True:
-                       pass #return
-
-               vingette_compression = 50
-
-               self.lookup_vingette = np.zeros((
-                       255 // vingette_compression + 1,
-                       self.display_size[0] // vingette_compression + 1,
-                       self.display_size[1] // vingette_compression + 1
-               ), dtype=np.uint8)
-
-               for v in range(0, 255, vingette_compression):
-                       pixel = np.array([[[0, 0, v]]], dtype=np.uint8)
-                       pixel = cv.cvtColor(pixel, cv.COLOR_HSV2BGR)
-
-                       self.display(pixel)
-                       #capture = self.capture()
-                       #capture = cv.cvtColor(capture, cv.COLOR_BGR2HSV)
-
-                       # apply vingette overlay
-                       capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
-
-                       rows = len(capture)
-                       columns = len(capture[0])
-                       for y, row in enumerate(capture):
-                               for x, pixel in enumerate(row):
-                                       y -= rows // 2
-                                       x -= columns // 2
-                                       math_pixel = pixel.astype(np.int16)
-                                       if x > y:
-                                               math_pixel += round(y * 0.0043)
-                                       else:
-                                               math_pixel += round(x * 0.0043)
-
-                                       pixel = np.clip(math_pixel, 0, 255).astype(np.uint8)
-
-
-                       for y in range(0, self.display_size[0], vingette_compression):
-                               for x in range(0, self.display_size[1], vingette_compression):
-                                       self.lookup_vingette[v // vingette_compression, y // vingette_compression, x // vingette_compression] = capture[y, x, 2] - v
-
-               color_compression = 90
+               if self.use_lookup == True:
+                       return
 
-               self.lookup_color = np.zeros((
-                       180 // color_compression + 1,
-                       255 // color_compression + 1,
-                       255 // color_compression + 1,
-                       3
-               ), dtype=np.uint8)
+               if self.use_files == True:
+                       self.lookup = np.load("lookup.npy")
+                       return
 
-               for h in range(0, 180, color_compression):
-                       for s in range(0, 255, color_compression):
-                               for v in range(0, 255, color_compression):
-                                       pixel = np.array([[[h, s, v]]], dtype=np.uint8)
-                                       pixel = cv.cvtColor(pixel, cv.COLOR_HSV2BGR)
+               lookup = None
 
+               for r in range(0, 255, self.lookup_compression):
+                       for g in range(0, 255, self.lookup_compression):
+                               for b in range(0, 255, self.lookup_compression):
+                                       pixel = np.array([[[b, g, r]]], dtype=np.int8)
+                                       pixel = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
                                        self.display(pixel)
-                                       #capture = self.capture()
-                                       #capture = cv.cvtColor(capture, cv.COLOR_BGR2HSV)
-
-                                       # apply the color ovelay
-                                       pixel = np.sin(pixel / (127.5 / np.pi)) * 2
-                                       pixel = np.clip(pixel, 0, 255)
-                                       capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
-
-                                       cx = self.display_size[1] // 2
-                                       cy = self.display_size[0] // 2
-                                       sample_diameter = 5
-                                       color = np.average(capture[cy - sample_diameter:cy + sample_diameter, cx - sample_diameter:cx + sample_diameter], axis=(0,1))
-
-                                       self.lookup_color[h // color_compression, s // color_compression, v // color_compression, 0:2] = color - [h, s, v]
-
-               np.save("lookup_vingette", self.lookup_vingette)
-               np.save("lookup_color", self.lookup_color)
 
-       def apply_lookup(
-               self,
-               image: np.ndarray
-       ) -> np.ndarray:
-               # must be given an array in the HSV color space
+                                       for i in range(10): # silly hack
+                                               time.sleep(0.2)
+                                               recovered = self.capture()
 
-               # apply the vingentte and color lookup table
-               for y, row in enumerate(image):
-                       for x, pixel in enumerate(row):
-                               pixel[2] += self.lookup_vingette[pixel[2] // self.lookup_compression][y // self.lookup_compression][x // self.lookup_compression]
-                               pixel = self.lookup_color[pixel[0] // self.lookup_compression][pixel[1] // self.lookup_compression][pixel[2] // self.lookup_compression]
+                                       error = np.copy(recovered.astype(np.int16))
+                                       error[..., 0] -= b
+                                       error[..., 1] -= g
+                                       error[..., 2] -= r
 
-               return image
-
-       def lookup_debug(
-               self,
-               tests: int
-       ) -> np.ndarray:
+                                       error = np.clip(error, -50, 255)
 
-               error_array = None
-
-               # begin loop over the desired sample size
-               for i in range(tests):
-                       pixel = [[[random.randint(0,255), random.randint(0,255), random.randint(0,255)]]]
-
-                       # apply the color ovelay
-                       pixel = np.sin(pixel / (127.5 / np.pi)) * 2
-                       pixel = np.clip(pixel, 0, 255)
-
-                       capture = cv.resize(pixel, self.display_size, interpolation=cv.INTER_NEAREST_EXACT)
-                       rows = len(capture)
-                       columns = len(capture[0])
-                       for y, row in enumerate(capture):
-                               for x, pixel in enumerate(y):
-                                       y -= rows
-                                       x -= columns
-                                       distance = np.sqrt((x ^ 2) + (y ^ 2)) * 0.02
-                                       pixel += distance
-                       capture = np.clip(capture, 0, 255)
-
-                       returned = self.apply_lookup(capture)
-                       self.display(returned)
-
-                       if error_array is None:
-                               error_array = error
-                       error_array = (error_array + error) / 2
+                                       if lookup is None:
+                                               lookup = error
+                                       else:
+                                               lookup += error
+                                               lookup  = lookup // 2
 
-               error_array = cv.cvtColor(error_array, cv.COLOR_BGR2HSV)
-               cv.imwrite("error_array.png", error_array)
+               self.lookup = lookup
+               np.save("lookup.npy", lookup)
 
        def display(
                self,
                                image = cv.warpPerspective(image, self.homography, self.display_size)
                                image = cv.resize(image, (self.window_size, self.window_height))
 
-               if self.lookup_vingette is not None and self.lookup_color is not None:
-                       pass
+                       if type(self.lookup) == np.ndarray and self.use_lookup == True:
+                               image = np.clip(image + self.lookup, 0, 255).astype(np.uint8)
 
                self.last_recovered = image