# @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


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)
    l, t, r, b = 9999, 9999, 0, 0
    sum_w, sum_h = 0, 0
    for ele in cnt:
        x, y, w, h = cv2.boundingRect(ele)
        xm = x + w
        ym = y + h
        l, t, r, b = min(l, x), min(t, y), max(r, xm), max(b, ym)
        sum_w, sum_h = sum_w + w, sum_h + h

    cols = len(cnt)
    if cols > 4:
        cols = 4
    single_width, single_height = int(sum_w / len(cnt)), int(sum_h / len(cnt))
    optional_solve_dict = {'rows': 1, 'cols': cols,
                           'single_width': single_width,
                           'single_height': single_height,
                           'bounding_box': {'xmin': l + left + single_width,
                                            'ymin': t + top,
                                            'xmax': r + left,
                                            'ymax': b + top}
                           }
    return optional_solve_dict


def resolve_optional_choice(ll, tt, direction, image):
    ocr_res = get_ocr_text_and_coordinate(image)
    # ocr_res = [{'chars': [{'char': '[', 'location': {'width': 16, 'top': 12, 'left': 11, 'height': 32}}, {'char': '4', 'location': {'width': 16, 'top': 12, 'left': 27, 'height': 32}}, {'char': '5', 'location': {'width': 16, 'top': 12, 'left': 36, 'height': 32}}, {'char': ']', 'location': {'width': 16, 'top': 12, 'left': 55, 'height': 32}}, {'char': '[', 'location': {'width': 16, 'top': 12, 'left': 74, 'height': 32}}, {'char': '4', 'location': {'width': 16, 'top': 12, 'left': 93, 'height': 32}}, {'char': '6', 'location': {'width': 16, 'top': 12, 'left': 102, 'height': 32}}, {'char': ']', 'location': {'width': 16, 'top': 12, 'left': 121, 'height': 32}}, {'char': '[', 'location': {'width': 16, 'top': 12, 'left': 140, 'height': 32}}, {'char': '4', 'location': {'width': 16, 'top': 12, 'left': 159, 'height': 32}}, {'char': '7', 'location': {'width': 16, 'top': 12, 'left': 178, 'height': 32}}, {'char': ']', 'location': {'width': 14, 'top': 12, 'left': 188, 'height': 32}}], 'location': {'width': 191, 'top': 12, 'left': 11, 'height': 32}, 'words': '[45][46][47]'}]
    digital_p = r'[\[*|【*]\d+[\]*|]*]'
    eng_char_p = '[[*|【*][A|B|C|D|E|F|G|T|F][]*|】*]'  # english

    pattern_list = [digital_p, eng_char_p]

    option_list = []
    mean_width_list = []
    mean_height_list = []
    for i, words_line in enumerate(ocr_res):
        words = words_line['words']
        words = words.replace(' ', '').upper()  # 去除空格
        loc = words_line['location']
        top = int(loc['top'])
        left = int(loc['left'])
        width = int(loc['width'])
        height = int(loc['height'])
        loc.update({'right': left + width, 'bottom': top + height,
                    'mid_x': left + width // 2, 'mid_y': top + height // 2})

        for p in pattern_list:
            words_m = re.finditer(p, words)
            match_index_list = [(m.group(), m.span()) for m in words_m if m]

            option_list += [ele[0].replace('[', '').replace(']', '').replace('【', ']').replace('】', '')
                            for ele in match_index_list]

            for letter_info in match_index_list:
                index_start = letter_info[1][0]
                index_end = letter_info[1][1] - 1
                char_start = words_line['chars'][index_start]
                char_end = words_line['chars'][index_end]

                letter_loc_xmin = int(char_start['location']['left'])
                letter_loc_ymin = min(int(char_start['location']['top']), int(char_end['location']['top']))
                letter_loc_xmax = int(char_end['location']['left']) + int(char_end['location']['width'])
                letter_loc_ymax = max(int(char_start['location']['top']) + int(char_start['location']['height']),
                                      int(char_end['location']['top']) + int(char_end['location']['height']))

                mean_width_list.append(letter_loc_xmax-letter_loc_xmin)
                mean_height_list.append(letter_loc_ymax-letter_loc_ymin)

    if not option_list:
        option_list = 'A,B'
    left = min([int(ele['location']['left']) for ele in ocr_res])
    top = min([int(ele['location']['top']) for ele in ocr_res])
    right = max([int(ele['location']['left']) + int(ele['location']['width']) for ele in ocr_res])
    bottom = max([int(ele['location']['top']) + int(ele['location']['height']) for ele in ocr_res])

    if direction == 180:
        rows, cols = 1, len(option_list)
    else:
        rows, cols = len(option_list), 1

    mean_width = sum(mean_width_list) // len(mean_width_list)
    mean_height = sum(mean_height_list) // len(mean_height_list)
    optional_choice_dict = {'rows': rows, 'cols': cols,
                            'option': ','.join(option_list),
                            'single_width': mean_width,
                            'single_height': mean_height,
                            'direction': direction,
                            'bounding_box': {'xmin': ll + left,
                                             'ymin': tt + top,
                                             'xmax': ll + right,
                                             'ymax': tt + bottom}}

    return optional_choice_dict
