from datetime import datetime

import cv2

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

from .check_current_product import CheckCurrentProductSolver
from .choose_product import ChooseProductSolver
from .get_remain_time import GetRemainTimeSolver
from .wait_for_product import WaitForProductSolver

production_time = {
    "经验": 180 * 60,
    "赤金": 72 * 60,
    "源石碎片": 60 * 60,
    "先锋双芯片": 60 * 60,
    "狙击双芯片": 60 * 60,
    "医疗双芯片": 60 * 60,
    "术师双芯片": 60 * 60,
    "近卫双芯片": 60 * 60,
    "重装双芯片": 60 * 60,
    "辅助双芯片": 60 * 60,
    "特种双芯片": 60 * 60,
}


class SwitchProductSolver(SceneGraphSolver, BaseMixin):
    def run(self, room, tar_product, only_get_time=False):
        logger.info(f"Start:切换产物 房间:{room} 目标产物:{tar_product}")
        EnterRoomSolver().run(room, detail=False)

        # 检查当前产物
        cur_product = CheckCurrentProductSolver().run(room)
        logger.info(f"当前产物:{cur_product}")
        if cur_product == tar_product:
            logger.info("当前产物已为目标产物")
            return True

        # 读取当前无人机数量避免重复开关
        cur_drone_count = DigitReader().get_drone(config.recog.gray)
        # 读取生产速度
        speed = self.read_speed()
        # 获取无人机加速的剩余时间
        remain_time = GetRemainTimeSolver().run(room)
        if only_get_time:
            return remain_time % production_time[cur_product] / speed
        # 使用无人机加速
        start_time = datetime.now()
        drone_count = remain_time % production_time[cur_product] // 180
        logger.info(f"应使用无人机数量:{drone_count}")
        if not DroneSolver().run(room, drone_count, cur_count=cur_drone_count):
            return False

        # 等待产物完成
        wait_time = max(
            remain_time % production_time[cur_product] % 180 / speed
            - (datetime.now() - start_time).total_seconds(),
            0,
        )

        logger.info(f"等待时间:{wait_time}")
        WaitForProductSolver().run(room, wait_time)

        # 选择目标产物
        if not ChooseProductSolver().run(room, tar_product):
            return False

        return True

    def number(self, scope: tp.Scope, height: int, thres: int) -> int:
        "数字识别"
        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)
        img = cv2.bitwise_not(img)
        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 < 8 and w < 8:
                value += "."
                continue
            elif h < 20 and w < 20:
                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_speed(self) -> float:
        speed1 = self.number(((1185, 955), (1255, 977)), 17, 120)
        speed2 = self.number(((1285, 955), (1355, 977)), 17, 150)
        return float(speed1) + float(speed2) + 1.0
