from datetime import datetime, timedelta

import cv2

from mower.models import Digtal
from mower.solvers.infra.base_mixin import BaseMixin
from mower.solvers.infra.enter_room import EnterRoomSolver
from mower.utils import config
from mower.utils import typealias as tp
from mower.utils.graph import SceneGraphSolver
from mower.utils.image import cropimg, thres2
from mower.utils.log import logger
from mower.utils.recognize import Scene


class GetOrderRemainingTimeSolver(SceneGraphSolver, BaseMixin):
    def run(self, room: str):
        logger.info("Start:读取订单剩余时间")
        self.room = room
        self.res = None
        if (
            self.scene() == Scene.ORDER_LIST
            and not self.detect_room_inside() == self.room
        ):
            EnterRoomSolver().run(self.room, detail=False)
        self.wait_start()
        super().run()
        return self.res

    def number(self, scope: tp.Scope, height: int, thres: int) -> str:
        "数字识别"
        img = cropimg(config.recog.gray, scope)
        default_height = 25
        if height != default_height:
            scale = 25 / height
            img = cv2.resize(img, None, None, scale, scale)
        img = thres2(img, thres)
        contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
        rect = [cv2.boundingRect(c) for c in contours]
        rect.sort(key=lambda c: c[0])

        value = ""
        for x, y, w, h in rect:
            if h < 10 and w < 10:
                value += ":"
                continue
            digit = cropimg(img, ((x, y), (x + w, y + h)))
            digit = cv2.copyMakeBorder(
                digit, 10, 10, 10, 10, cv2.BORDER_CONSTANT, None, (0,)
            )
            score = []
            for i in range(10):
                im = Digtal().riic_base_digits[i]
                result = cv2.matchTemplate(digit, im, cv2.TM_SQDIFF_NORMED)
                min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
                score.append(min_val)
            value += str(score.index(min(score)))

        return value

    def read_remain_time(self, pos) -> int:
        h, m, s = self.number(pos, 19, 115).split("::")
        return int(h) * 3600 + int(m) * 60 + int(s)

    def timeout(self) -> bool:
        return datetime.now() > self.start_time + timedelta(seconds=10)

    def wait_start(self):
        self.start_time = datetime.now()

    def transition(self) -> bool:
        if (scene := self.scene()) == Scene.INFRA_DETAILS:
            self.ctap((200, 1000), 1, config.screenshot_avg / 1000)
            self.wait_start()
        elif scene == Scene.ORDER_LIST:
            if self.timeout():
                logger.error("读取订单失败")
                return True
            elif pos := self.find("bill_accelerate"):
                pos[0][0] += 69
                pos[0][1] -= 214
                pos[1][0] -= 52
                pos[1][1] -= 220
                if res := self.read_remain_time(pos):
                    self.res = res
                    return True

        elif scene in self.waiting_scene:
            self.waiting_solver()
        else:
            EnterRoomSolver().run(self.room, detail=False)
