import os
import numpy as np
import time
from Object import computeDistance
from copy import deepcopy

anchors_path = os.path.expanduser("yolo3/model_data/yolo_anchors.txt")
classes_path = os.path.expanduser("yolo3/model_data/coco_classes.txt")
from PIL import Image, ImageDraw, ImageFont
import random
import colorsys

def contains(list, filter):
    for x in list:
        if x.name == filter:
            return True
    return False

def mse(imageA, imageB):
    # the 'Mean Squared Error' between the two images is the
    # sum of the squared difference between the two images;
    # NOTE: the two images must have the same dimension
    err = np.sum((imageA.astype("float") - imageB.astype("float")) ** 2)
    err /= float(imageA.shape[0] * imageA.shape[1])

    # return the MSE, the lower the error, the more "similar"
    # the two images are
    return err

def initProgram():
    with open(classes_path) as f:
        class_names = f.readlines()
    class_names = [c.strip() for c in class_names]

    with open(anchors_path) as f:
        anchors = f.readline()
        anchors = [float(x) for x in anchors.split(',')]
        anchors = np.array(anchors).reshape(-1, 2)

    return class_names, anchors

def timing(f):
    def wrap(*args):
        time1 = time.time()
        ret = f(*args)
        time2 = time.time()
        print('function took %0.3f ms' % ((time2-time1)*1000.0))
        return ret
    return wrap

def computeCurveDifference(Object, Object2):

    x1,y1 = Object.getXY()
    x2,y2 = Object2.getXY()
    totalDistance = 0

    if len(x1) == len(x2) and len(y1) == len(y2) and len(y1) == len(x1):
        for i in range(len(x1)):
            totalDistance += computeDistance(x1.pop(),y1.pop(), x2.pop(), y2.pop())
    else:
        totalDistance = 9999999
    return totalDistance


def processMemory(newObjects, memory):

    for newObject in newObjects:
        copy = False


        for objectFromMemory in memory:

            if newObject.name == objectFromMemory.name :
                if copy == False:
                    objectFromMemory.img = newObject.img
                    objectFromMemory.name = newObject.name
                    objectFromMemory.classification = newObject.classification
                    objectFromMemory.X = newObject.X
                    objectFromMemory.Y = newObject.Y
                    objectFromMemory.computeCenterPosition()
                    objectFromMemory.timestamp = time.time()
                    objectFromMemory.lastOwner = newObject.lastOwner
                    copy = True

        newObject.timestamp = time.time()
        memory.append(deepcopy(newObject))


    for i in range(len(memory)):
        if time.time() - memory[i].timestamp > 5:
            del memory[i]
            break


def drawBoxes(image, objects, class_names, correlations, debug, alarms):

            font = ImageFont.truetype(font='font/FiraMono-Medium.otf',
                                      size=np.floor((3e-2 * image.size[1] + 0.5)).astype('int32'))
            thickness = (image.size[0] + image.size[1]) // 300

            hsv_tuples = [(x / len(class_names), 1., 1.)
                          for x in range(len(class_names))]

            colors = list(map(lambda x: colorsys.hsv_to_rgb(*x), hsv_tuples))
            colors = list(
                map(lambda x: (int(x[0] * 255), int(x[1] * 255), int(x[2] * 255)),
                    colors))
            random.seed(101010)  # Fixed seed for consistent colors across runs.
            random.shuffle(colors)  # Shuffle colors to decorrelate adjacent classes.
            random.seed(None)  # Reset seed to default.

            if debug == True:
                for object in objects:
                    label = '{}'.format(object.name)

                    draw = ImageDraw.Draw(image)
                    label_size = draw.textsize(label, font)

                    top = max(0, np.floor(object.top + 0.5).astype('int32'))
                    left = max(0, np.floor(object.left + 0.5).astype('int32'))
                    bottom = min(image.size[1], np.floor(object.bottom + 0.5).astype('int32'))
                    right = min(image.size[0], np.floor(object.right + 0.5).astype('int32'))

                    if top - label_size[1] >= 0:
                        text_origin = np.array([left, top - label_size[1]])
                    else:
                        text_origin = np.array([left, top + 1])

                    # My kingdom for a good redistributable image drawing library.
                    for i in range(thickness):
                        draw.rectangle(
                            [left + i, top + i, right - i, bottom - i],
                            outline=colors[class_names.index(object.classification)])
                    draw.rectangle(
                        [tuple(text_origin), tuple(text_origin + label_size)],
                        fill=colors[class_names.index(object.classification)])
                    draw.text(text_origin, label, fill=(0, 0, 0), font=font)

                    del draw

                draw = ImageDraw.Draw(image)

                for correlation in correlations:
                    draw.line((correlation.x1, correlation.y1, correlation.x2, correlation.y2), fill=(0, 255, 0, 0))

                del draw

            for object in alarms:

                label = "Abandoned laggage"
                draw = ImageDraw.Draw(image)
                label_size = draw.textsize(label, font)

                top = max(0, np.floor(object.top + 5).astype('int32'))
                left = max(0, np.floor(object.left + 5).astype('int32'))
                bottom = min(image.size[1], np.floor(object.bottom + 5).astype('int32'))
                right = min(image.size[0], np.floor(object.right + 5).astype('int32'))

                if top - label_size[1] >= 0:
                    text_origin = np.array([left, top - label_size[1]])
                else:
                    text_origin = np.array([left, top + 1])

                for i in range(thickness):
                    draw.rectangle(
                        [left + i, top + i, right - i, bottom - i],
                        outline=(0, 0, 255, 0))
                draw.rectangle(
                    [tuple(text_origin), tuple(text_origin + label_size)],
                    fill=(0, 0, 255, 0))
                draw.text(text_origin, label, fill=(0, 0, 0), font=font)

                del draw

            return image


