# import the necessary packages
from skimage.measure import compare_ssim
import numpy as np
import cv2
from hallopy import utils


class ImageTestTool:
    """This class contain tools that helps test functionality"""

    @staticmethod
    def compare_imaged(img1, img2):
        """This function compare 2 images.

        Return SSIM:    Represents the structural similarity index between the two input images.
                        This value can fall into the range [-1, 1] with a value of one being a “perfect match”.
        """

        # load the two input images
        imageA = img1
        imageB = img2

        # convert the images to grayscale
        grayA = cv2.cvtColor(imageA, cv2.COLOR_BGR2GRAY)
        grayB = cv2.cvtColor(imageB, cv2.COLOR_BGR2GRAY)

        # compute the Structural Similarity Index (SSIM) between the two
        # images, ensuring that the difference image is returned
        (score, diff) = compare_ssim(grayA, grayB, full=True)
        # diff = (diff * 255).astype("uint8")
        return score
        # print("SSIM: {}".format(score))
        #
        # # threshold the difference image, followed by finding contours to
        # # obtain the regions of the two input images that differ
        # thresh = cv2.threshold(diff, 0, 255,
        #                        cv2.THRESH_BINARY_INV | cv2.THRESH_OTSU)[1]
        # cnts = cv2.findContours(thresh.copy(), cv2.RETR_EXTERNAL,
        #                         cv2.CHAIN_APPROX_SIMPLE)
        # cnts = cnts[0] if imutils.is_cv2() else cnts[1]
        #
        # # loop over the contours
        # for c in cnts:
        #     # compute the bounding box of the contour and then draw the
        #     # bounding box on both input images to represent where the two
        #     # images differ
        #     (x, y, w, h) = cv2.boundingRect(c)
        #     cv2.rectangle(imageA, (x, y), (x + w, y + h), (0, 0, 255), 2)
        #     cv2.rectangle(imageB, (x, y), (x + w, y + h), (0, 0, 255), 2)
        #
        # # show the output images
        # cv2.imshow("Original", imageA)
        # cv2.imshow("Modified", imageB)
        # cv2.imshow("Diff", diff)
        # cv2.imshow("Thresh", thresh)
        # cv2.waitKey(0)

    @staticmethod
    def detect_faces(img):
        """Function for detecting faces.

        :returns faces: array with detected faces coordination's.
        """

        face_detector = cv2.CascadeClassifier(utils.get_full_path('hallopy/config/haarcascade_frontalface_default.xml'))
        gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        return face_detector.detectMultiScale(gray, 1.3, 5)

    @staticmethod
    def draw_black_recs(img, obj_coord):
        # Black rectangle over faces to remove skin noises.
        for (x, y, w, h) in obj_coord:
            img[y:y + h, x:x + w, :] = 0

    @staticmethod
    def clip_roi(img, roi):
        clipped = img[0:int(roi['cap_region_y_end'] * img.shape[0]),
                  int(roi['cap_region_x_begin'] * img.shape[1]):img.shape[1]]  # clip the ROI
        return clipped

    @staticmethod
    def get_max_area_contour(input_image):
        # Get the contours.
        expected_gray = cv2.cvtColor(input_image, cv2.COLOR_BGR2GRAY)
        blur = cv2.GaussianBlur(expected_gray, (41, 41), 0)
        thresh = cv2.threshold(blur, 50, 255, cv2.THRESH_BINARY)[1]
        thresh = cv2.erode(thresh, None, iterations=2)
        thresh = cv2.dilate(thresh, None, iterations=2)
        _, contours, hierarchy = cv2.findContours(thresh, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)

        # Find the biggest area
        try:
            if len(contours) > 0:
                max_area_contour = max(contours, key=cv2.contourArea)
                return max_area_contour
        except ValueError as error:
            print(error)

    @staticmethod
    def get_contour_area(contour):
        return cv2.contourArea(contour)

    @staticmethod
    def get_center_of_mass(contour):
        """Find contours center of mass.  """
        M = cv2.moments(contour)
        if M["m00"] != 0:
            cX = int(M["m10"] / M["m00"])
            cY = int(M["m01"] / M["m00"])
        else:
            cX, cY = 0, 0

        return cX, cY

    @staticmethod
    def get_middle_finger_edge_coord(contour):
        """Function for calculating middle finger edge coordination.
        :type contour: collection.iter
        """

        temp_y = 1000
        for point in contour:  # find highest point in contour, and track that point
            if point[0][1] < temp_y:
                temp_y = point[0][1]

        return point[0][0], point[0][1]

    @staticmethod
    def get_contour_extreme_points(contour):
        c = contour
        try:
            # determine the most extreme points along the contour
            extLeft = tuple(c[c[:, :, 0].argmin()][0])
            extRight = tuple(c[c[:, :, 0].argmax()][0])
            extTop = tuple(c[c[:, :, 1].argmin()][0])
            extBot = tuple(c[c[:, :, 1].argmax()][0])
        except TypeError as error:
            extLeft = 0, 0
            extRight = 0, 0
            extTop = 0, 0
            extBot = 0, 0

        return extLeft, extRight, extTop, extBot

    @staticmethod
    def draw_contours(image, contours):
        cv2.drawContours(image, [contours], -1, (0, 255, 255), 2)

    @staticmethod
    def draw_tracking_points(image, points):

        # draw the outline of the object, then draw each of the
        # extreme points, where the left-most is red, right-most
        # is green, top-most is blue, and bottom-most is teal
        # determine the most extreme points along the contour
        c = points.reshape(-1, 1, 2)
        if points.size > 0:
            # only ext_contour points have been given.
            # ext_left = tuple(c[c[:, :, 0].argmin()][0])
            # ext_right = tuple(c[c[:, :, 0].argmax()][0])
            ext_top = tuple(c[c[:, :, 1].argmin()][0])
            ext_bot = tuple(c[c[:, :, 1].argmax()][0])
            # palm_center = points[4]
            # cv2.circle(image, ext_left, 8, (0, 0, 255), -1)
            # cv2.putText(image,'ext_left',ext_left, cv2.FONT_HERSHEY_COMPLEX, .5, (0, 0, 255))

            # cv2.circle(image, ext_right, 8, (0, 255, 0), -1)
            # cv2.putText(image,'ext_right',ext_right, cv2.FONT_HERSHEY_COMPLEX, .5, (0, 255, 0))

            cv2.circle(image, ext_top, 8, (255, 0, 0), -1)
            cv2.putText(image, 'ext_top', ext_top, cv2.FONT_HERSHEY_COMPLEX, .5, (255, 0, 0))

            cv2.circle(image, ext_bot, 8, (255, 255, 0), -1)
            cv2.putText(image, 'ext_bot', ext_bot, cv2.FONT_HERSHEY_COMPLEX, .5, (255, 255, 0))
            # cv2.circle(image, palm_center, 8, (255, 255, 255), thickness=-1)