import os.path
import re
import sys
from urllib.parse import unquote
import numpy
import win32gui
from PIL import ImageGrab, Image, ImageQt
from airclick.utils import screen_utils
from airclick.daos.screen_daos import Point, OcrRes
import numpy as np

from airclick.utils.screen_utils import compare_colors
from airclick.windows.system import R
from airclick.utils import airclickcv as aircv


def capture(hwnd: int = 0, rect=None) -> Image:
    temp_img = None
    if hwnd != 0:
        temp_rect = win32gui.GetWindowRect(hwnd)
        temp_img = ImageGrab.grab(temp_rect)
    else:
        temp_img = ImageGrab.grab()

    if rect:
        temp_img = temp_img.crop(rect)
    return temp_img


def get_color(x, y):
    img = capture()
    return img.getpixel((x, y))


class FindColors:
    def __init__(self, colors: str = None, rect=[], sim: float = 0.9, ore: int = 2, space: int = 5, file: str = None,
                 dict_p: dict = None):
        self.rect = rect
        self.colors = colors
        self.sim = sim
        self.ore = ore
        self.space = space
        self.res_num = 1
        self.file = file

        if dict_p:
            if 'colors' in dict_p:
                self.colors = dict_p['colors']

            if 'rect' in dict_p:
                self.rect = dict_p['rect']

            if 'sim' in dict_p:
                self.sim = float(dict_p['sim'])

            if 'ore' in dict_p:
                self.ore = int(dict_p['ore'])

            if 'space' in dict_p:
                self.space = int(dict_p['space'])

            if 'file' in dict_p:
                self.file = unquote(dict_p['file'])

            if 'res_num' in dict_p:
                self.res_num = int(dict_p['res_num'])

    def find(self):
        self.res_num = 1
        res = self.exec_find()
        if res and len(res) > 0:
            return res[0]
        return None

    def find_all(self, res_num=sys.maxsize):
        self.res_num = res_num
        res = self.exec_find()
        if res or len(res) > 0:
            return res
        return None

    def exec_find(self):
        # 获取截图
        img = None
        if self.file:
            img = Image.open(self.file)
        else:
            img = ImageGrab.grab()

        if self.rect and len(self.rect) == 4:
            img = img.crop(self.rect)

        # 回填 坐标
        ps = screen_utils.find_colors(self.colors, self.sim, self.res_num, self.ore, img, self.space)
        if ps and self.rect and len(self.rect) == 4:
            for i in range(len(ps)):
                ps[i] = Point(ps[i].x + self.rect[0], ps[i].y + self.rect[1])

        return ps


class CompareColors:
    def __init__(self, colors: str = None, sim: float = 0.9, img_file: str = None, dict_p: dict = None):
        self.colors = colors
        self.sim = sim
        self.img_file = img_file
        if dict_p:
            if 'colors' in dict_p:
                self.colors = dict_p['colors']

            if 'sim' in dict_p:
                self.sim = float(dict_p['sim'])

            if 'path' in dict_p:
                self.img_file = unquote(dict_p['path'])

    def compare(self):
        if self.img_file:
            img = Image.open(self.img_file)
        else:
            img = capture()

        return compare_colors(self.colors, self.sim, img)


class Ocr:
    def __init__(self, rect=[], pattern: str = None, confidence: float = 0.1, img_path: str = None,
                 dict_p: dict = None):

        self.rect = rect
        self.pattern = pattern
        self.confidence = confidence
        self.img_path = img_path
        # self.ocr = PaddleOCR(ocr_version='PP-OCRv3')

        if dict_p:
            if 'rect' in dict_p:
                self.rect = dict_p['rect']

            if 'pattern' in dict_p:
                self.pattern = dict_p['pattern']

            if 'img_path' in dict_p:
                self.img_path = unquote(dict_p['img_path'])

            if 'confidence' in dict_p:
                self.sim = float(dict_p['confidence'])

            if 'findtype' in dict_p:
                if dict_p['findtype'] == 'find':
                    self.res_num = 1
                else:
                    self.res_num = 0

        # from easyocr import Reader
        #
        # self.ocr = Reader(['en', 'ch_sim'])

        from paddleocr import PaddleOCR
        self.ocr = PaddleOCR()

    def find(self) -> OcrRes:
        self.res_num = 1
        res = self.exec_find_paddle()
        if res:
            return res[0]
        return None

    def find_all(self, res_num: int = 0) -> [OcrRes]:
        self.res_num = res_num
        res = self.exec_find_paddle()
        return res

    def exec_find(self):
        if self.img_path:
            img = Image.open(self.img_path)
        else:
            img = capture(rect=self.rect)

        if self.rect and len(self.rect) == 4:
            img = img.crop(self.rect)

        # res_source = self.ocr.readtext(np.array(img))

        res_source = self.ocr.ocr(np.array(img))

        print(res_source)

        res = []
        if res_source:
            for r in res_source:
                if self.pattern:
                    pattern = re.compile(self.pattern)
                if r[2] >= self.confidence and (self.pattern is None or pattern.match(r[1])):

                    offsetx = 0
                    offsety = 0
                    if self.rect:
                        offsetx = self.rect[0]
                        offsety = self.rect[1]

                    region_position = r[0]
                    region_position = [[int(region_position[0][0]) + offsetx, int(region_position[0][1]) + offsety],
                                       [int(region_position[1][0]) + offsetx, int(region_position[1][1]) + offsety],
                                       [int(region_position[2][0]) + offsetx, int(region_position[2][1]) + offsety],
                                       [int(region_position[3][0]) + offsetx, int(region_position[3][1]) + offsety]]

                    if self.res_num == 0:
                        res.append(OcrRes(text=r[1], confidence=r[2], region_position=region_position))
                    elif len(res) < self.res_num:
                        res.append(OcrRes(text=r[1], confidence=r[2], region_position=region_position))
                    else:
                        return res

        return res

    def exec_find_paddle(self):
        if self.img_path:
            img = Image.open(self.img_path)
        else:
            img = capture(rect=self.rect)

        if self.rect and len(self.rect) == 4:
            img = img.crop(self.rect)

        res_source = self.ocr.ocr(np.array(img))
        res = []
        if res_source and res_source[0]:
            for r in res_source[0]:

                if self.pattern:
                    pattern = re.compile(self.pattern)
                    # [ [[238.0, 12.0], [330.0, 12.0], [330.0, 40.0], [238.0, 40.0]], ('版本控制', 0.9998359680175781)]

                if r[1][1] >= self.confidence and (self.pattern is None or pattern.match(r[1][0])):

                    offsetx = 0
                    offsety = 0
                    if self.rect:
                        offsetx = int(self.rect[0])
                        offsety = int(self.rect[1])

                    region_position = r[0]
                    region_position = [[int(region_position[0][0]) + offsetx, int(region_position[0][1]) + offsety],
                                       [int(region_position[1][0]) + offsetx, int(region_position[1][1]) + offsety],
                                       [int(region_position[2][0]) + offsetx, int(region_position[2][1]) + offsety],
                                       [int(region_position[3][0]) + offsetx, int(region_position[3][1]) + offsety]]

                    if self.res_num == 0:
                        res.append(OcrRes(text=r[1][0], confidence=r[1][1], region_position=region_position))
                    elif len(res) < self.res_num:
                        res.append(OcrRes(text=r[1][0], confidence=r[1][1], region_position=region_position))
                    else:
                        return res

        return res

    def to_dict(self):
        pass


class FindImages:

    def __init__(self, img_part: str = None, source_rect=None, source_file: str = None, confidence: float = 0.1,
                 dict_p: dict = None):

        self.img_part = img_part
        self.source_rect = source_rect
        self.source_file = source_file
        self.confidence = confidence

        if dict_p:
            if 'image' in dict_p:
                self.img_part = dict_p['image']

            if 'screen' in dict_p:
                self.source_file = unquote(dict_p['screen'])

            if 'sim' in dict_p:
                self.confidence = float(dict_p['sim'])
        else:
            if not os.path.exists(self.img_part):
                self.img_part = R().file("res/img/" + img_part)
                if not os.path.exists(self.img_part):
                    raise ValueError('图片路径不存在:' + self.img_part)

        self.source_img = numpy.array(self.__get_source_img())
        self.search_img = numpy.array(Image.open(self.img_part))

        # self.source_img = cv2.imread("D:\\work\\test\\ac_client\\assets\\tools\\capture\\1703126140.png")
        # self.search_img = cv2.imread("D:\\work\\test\\res\\img\\c.png")

    def find(self, various_size=False):

        res = self.find_template()
        if res:
            return res

        res = self.find_sift()

        return res

    def find_all(self, maxcnt: int = 0, various_size=False):
        res = self.find_all_template()
        if res and len(res)>0:
            return res

        res = self.find_all_sift()
        return res

    def find_sift(self, min_match_count: int = 4):
        res = self.find_all_sift(maxcnt=1)
        if not res:
            return None
        return res[0]

    def find_all_sift(self, min_match_count: int = 4, maxcnt=0):
        res = aircv.find_all_sift(self.source_img, self.search_img, min_match_count, maxcnt)

        f_res = []
        for r in res:
            if r['confidence'] >= self.confidence:
                f_res.append(r)

        return f_res

    # def find_all_sift_gpt(self, min_match_count: int = 4, maxcnt=0):
    #     return aircv.find_all_sift_gpt(self.source_img, self.search_img, min_match_count, maxcnt)

    def find_template(self, threshold=0.5, rgb=False, bgremove=False):
        f_res = self.find_all_template(maxcnt=1, threshold=threshold, rgb=rgb, bgremove=bgremove)
        if f_res and len(f_res) > 0:
            return f_res[0]
        return None

    def find_all_template(self, maxcnt=0, threshold=0.5, rgb=False, bgremove=False):

        res = aircv.find_all_template(self.source_img, self.search_img, threshold, maxcnt, rgb, bgremove)

        f_res = []
        for r in res:
            if r['confidence'] >= self.confidence:
                f_res.append(r)

        return f_res

    def __get_source_img(self):
        temp_img = None
        if self.source_file:
            temp_img = Image.open(self.source_file)
        else:
            temp_img = capture()

        if self.source_rect and self.source_img.size == 4:
            temp_img = temp_img.resize(self.source_rect)

        return temp_img
