# @Author  : lightXu
# @File    : optional_solve.py
# @Time    : 2019/9/17 0017 下午 13:18
import cv2
import re
from segment.sheet_resolve.tools.brain_api import get_ocr_text_and_coordinate
from segment.sheet_resolve.analysis.sheet.choice_infer import find_digital


def rgb2binary(im):
    gray_img = cv2.cvtColor(im, cv2.COLOR_BGR2GRAY)
    _ret, thresh_img = cv2.threshold(gray_img, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
    return thresh_img


def find_contours(left, top, image, ex_x=30, ex_y=1):
    threshed = rgb2binary(image)
    kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (ex_x, ex_y))  # 膨胀系数
    # morphed = cv2.morphologyEx(threshed, cv2.MORPH_CLOSE, kernel)
    morphed = cv2.dilate(threshed, kernel, iterations=1)

    (major, minor, _) = cv2.__version__.split(".")
    contours = cv2.findContours(morphed, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    cnts = contours[0] if int(major) > 3 else contours[1]

    cnt = sorted(cnts, key=cv2.contourArea)
    boxes = []
    for ele in cnt:
        x, y, w, h = cv2.boundingRect(ele)
        x_mid = x + w//2
        y_mid = y + h//2
        xmax = x+w
        ymax = y+h
        boxes.append((x, y, xmax, ymax, x_mid,y_mid))

    return boxes


def point_in_polygon(point, polygon):
    xmin, ymin, xmax, ymax = polygon[0], polygon[1], polygon[2], polygon[3]
    if xmin <= point[0] <= xmax and ymin <= point[1] <= ymax:
        return True
    else:
        return False


def resolve_optional_choice(l_, t_, direction, image):
    ocr_res = get_ocr_text_and_coordinate(image)
    digital_list, chars_list, d_mean_height, d_mean_width = find_digital(ocr_res, 0, 0,)
    if not digital_list:
        numbers = [501, 502]
        h, w = image.shape
        optional_choice_dict = {'class_name': 'optional_choice',
                                'rows': 1, 'cols': 2,
                                'single_width': w,
                                'single_height': h,
                                'direction': direction,
                                'bounding_box': {'xmin': l_,
                                                 'ymin': t_,
                                                 'xmax': l_ + w,
                                                 'ymax': t_ + h},
                                'number': numbers}
    else:
        numbers = sorted([ele['digital'] for ele in digital_list])

        contours = find_contours(l_, t_, image, d_mean_width*2, d_mean_height)

        res_region = []
        for contour in contours:
            for num in digital_list:
                loc = num['loc']
                num_center = (loc[-2], loc[-1])
                if point_in_polygon(num_center, contour):
                    if num_center[0] < contour[-2] - d_mean_width//3:
                        # 数字在box的左侧
                        region = (loc[2]+1, loc[1]-1, contour[2]-3, loc[3]+1)
                    else:
                        # 数字在box中间, 数字在box左侧
                        region = (contour[0], loc[1] - 1, contour[2], loc[3] + 1)
                    res_region.append(region)

        l, t, r, b = 9999, 9999, 0, 0
        sum_w, sum_h = 0, 0
        for region in res_region:
            l, t, r, b = min(l, region[0]), min(t, region[1]), max(r, region[2]), max(b, region[3])

            width, height = region[2] - region[0], region[3] - region[1]
            sum_w += width
            sum_h += height

        mean_w, mean_h = sum_w//len(numbers), sum_h//len(numbers)

        if direction == 180:
            rows, cols = 1, max(2, len(numbers))
            if len(numbers) < 2:
                numbers.append(501)
        else:
            rows, cols = max(2, len(numbers)), 1
            if len(numbers) < 2:
                numbers.append(501)

        optional_choice_dict = {'class_name': 'optional_choice',
                                'rows': rows, 'cols': cols,
                                'single_width': mean_w,
                                'single_height': mean_h,
                                'direction': direction,
                                'bounding_box': {'xmin': l_ + l,
                                                 'ymin': t_ + t,
                                                 'xmax': l_ + r,
                                                 'ymax': t_ + b},
                                'number': numbers}

    # print(optional_choice_dict)
    return optional_choice_dict
