import colorsys
from utils import timing
import random
import time
import numpy as np
from PIL import Image, ImageDraw, ImageFont
from keras import backend as K
from correlation import Correlation


class yoloWrapper(object):


    @classmethod
    def getObjectsFromImage(self,image, sess, yolo_model, anchors, class_names, boxes, scores, classes, input_image_shape):

        model_image_size = yolo_model.layers[0].input_shape[1:3]
        is_fixed_size = model_image_size != (None, None)

        if is_fixed_size:
            resized_image = image.resize(
                tuple(reversed(model_image_size)), Image.BICUBIC)
            image_data = np.array(resized_image, dtype='float32')
        else:
            new_image_size = (image.width - (image.width % 32),image.height - (image.height % 32))
            resized_image = image.resize(new_image_size, Image.BICUBIC)
            image_data = np.array(resized_image, dtype='float32')

        image_data /= 255.
        image_data = np.expand_dims(image_data, 0)  # Add batch dimension.


        out_boxes, out_scores, out_classes = sess.run(
                [boxes, scores, classes],
                feed_dict={
                    yolo_model.input: image_data,
                    input_image_shape: [image.size[1], image.size[0]],
                    K.learning_phase(): 0
                })


        return out_classes, class_names, out_boxes, out_scores

    @classmethod
    def drawBoxes(self,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