import cv2
import time
import serial
from xmlrpc.server import SimpleXMLRPCServer
from xmlrpc.server import SimpleXMLRPCRequestHandler
from threading import Thread
import numpy as np

cap = cv2.VideoCapture(-1)
font = cv2.FONT_HERSHEY_SIMPLEX
list_img = cv2.imread('list.jpg')
list_img = cv2.resize(list_img,None,fx=0.8, fy=0.8, interpolation = cv2.INTER_CUBIC)
target_w = 50
candy1_img = cv2.imread('candy1.jpg')
factor = target_w / candy1_img.shape[0]
candy1_img = cv2.resize(candy1_img,None,fx=factor, fy=factor, interpolation = cv2.INTER_CUBIC)
candy2_img = cv2.imread('candy2.jpg')
factor = target_w / candy2_img.shape[0]
candy2_img = cv2.resize(candy2_img,None,fx=factor, fy=factor, interpolation = cv2.INTER_CUBIC)
candy3_img = cv2.imread('candy3.jpg')
factor = target_w / candy3_img.shape[0]
candy3_img = cv2.resize(candy3_img,None,fx=factor, fy=factor, interpolation = cv2.INTER_CUBIC)
candy4_img = cv2.imread('candy4.jpg')
factor = target_w / candy4_img.shape[0]
candy4_img = cv2.resize(candy4_img,None,fx=factor, fy=factor, interpolation = cv2.INTER_CUBIC)
img_list = [candy1_img, candy2_img, candy3_img, candy4_img]

IMG_W = 1280
IMG_H = 720
rect_w = 220
rect_h = 52

weights_list = [37.0, 4.8, 8.8, 2.5]

ARDUPORT = 'COM12'
serial = serial.Serial(ARDUPORT, 115200, timeout=1)

candy_stat = []
# s = {}
# s['img_idx'] = 0
# s['loaded'] = 0
# s['required'] = 4
# candy_stat.append(s)
# s = {}
# s['img_idx'] = 1
# s['loaded'] = 0
# s['required'] = 2
# candy_stat.append(s)
# s = {}
# s['img_idx'] = 2
# s['loaded'] = 0
# s['required'] = 6
# candy_stat.append(s)
# s = {}
# s['img_idx'] = 3
# s['loaded'] = 0
# s['required'] = 9
# candy_stat.append(s)

previous_weight = 0

def new_order(params):
	candy_stat = params

def async_server_megahack(server):
	server.serve_forever()

# Restrict to a particular path.
class RequestHandler(SimpleXMLRPCRequestHandler):
	rpc_paths = ('/RPC2',)

def check_endgame(params):
	for s in candy_stat:
		if s['required'] != s['loaded']:
			return False
	return True
def is_equal_with_tolerance(v1, v2, t):
	return (v2 * (1-t) <  v1) and (v2 * (1+t) > v1)

did_change = False
def check_weights(params, new_weight):
	global previous_weight, did_change
	weight_diff = new_weight - previous_weight
	if weight_diff < 0.3:
		return
	elif not did_change:
		did_change = True
	else:
		for i in range(4):
			if is_equal_with_tolerance(weight_diff, weights_list[i], 0.1):
				params[i]['loaded'] += 1
				previous_weight = new_weight
				did_change = False
				break
		if did_change:
			did_change = False
			previous_weight = new_weight

def draw_rectangles(img, n):
	for i in range(n):
		cv2.rectangle(img, (IMG_W - 5 - rect_w,5 + (rect_h + 5)*i), (IMG_W - 5, 5 + (rect_h + 5)*i + rect_h), (255, 255, 255), -1)

def print_stats(img, stats):
	# draw_rectangles(img, len(stats))
	img[0:list_img.shape[0], IMG_W-list_img.shape[1]:IMG_W, :] = list_img[:]
	for i in range(len(stats)):
		cv2.putText(img,str(stats[i]['loaded']),(IMG_W - 130,188 + i * (rect_h + 5)), font, 1.3,(0, 0, 0),2,cv2.LINE_AA)
		cv2.putText(img,"/",(IMG_W - 90,188 + i * (rect_h + 5)), font, 1.3,(0, 0, 0),2,cv2.LINE_AA)
		cv2.putText(img,str(stats[i]['required']),(IMG_W - 50,188 + i * (rect_h + 5)), font, 1.3,(0, 0, 0),2,cv2.LINE_AA)
		img[150+(rect_h + 5)*i:150+(rect_h + 5)*i + target_w, IMG_W-130-target_w-20:IMG_W-130-20, :] = img_list[stats[i]['img_idx']][:]

cv2.namedWindow("window", cv2.WND_PROP_FULLSCREEN)
cv2.setWindowProperty("window",cv2.WND_PROP_FULLSCREEN,cv2.WINDOW_FULLSCREEN)
with SimpleXMLRPCServer(('localhost', 8000),
						requestHandler=RequestHandler) as server:
	server.register_introspection_functions()

	server.register_function(new_order)

	t = Thread(target=async_server_megahack, args=(server,))
	t.start()
	# serial.write(b'e')
	# line = serial.readline()[:-2]
	# print (line)
	# weight = -float(line)
	# previous_weight = weight
	frame_counter = 0
	weight = 0
	canvas = np.zeros((720, 1280, 3)).astype(np.uint8)
	while True:
		
		frame_counter += 1
		if frame_counter == 75:
			serial.write(b'e')
			weight = -float(serial.readline()[:-2])
			frame_counter = 0
			print(weight)
			check_weights(candy_stat, weight)
			if check_endgame(candy_stat):
				candy_stat = []
				# TODO: do funny gif
		ret, frame = cap.read()
		frame = cv2.resize(frame,None,fx=1.5, fy=1.5, interpolation = cv2.INTER_CUBIC)
		canvas[0:720, 0:960, :] = frame[:]
		if (len(candy_stat) > 0):
			print_stats(canvas, candy_stat)
		cv2.imshow("window", canvas)
		if cv2.waitKey(1) & 0xFF == ord('q'):
			break

# When everything done, release the capture
cap.release()
cv2.destroyAllWindows()