from datetime import datetime
from typing import Literal

import cv2

from mower.utils import config
from mower.utils.graph import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.scene import Scene
from mower.utils.vector import va, vs

from .utils import generate_name


class classproperty:
    def __init__(self, method=None):
        self.fget = method

    def __get__(self, instance, cls=None):
        return self.fget(cls)

    def getter(self, method):
        self.fget = method
        return self


class ActivityNavigation(SceneGraphSolver):
    solver_name = "活动关卡导航"

    _location = {
        "normal": {
            "RS-1": (0, 0),
            "RS-2": [408, 135],
            "RS-3": [767, 0],
            "RS-4": [1102, 135],
            "RS-5": [1779, 135],
            "RS-6": [2233, 0],
            "RS-7": [2856, 274],
            "RS-8": [2856, 0],
        },
        "ex": {
            "RS-EX-1": (0, 0),
            "RS-EX-2": [430, 0],
            "RS-EX-3": [860, 0],
            "RS-EX-4": [1289, 0],
            "RS-EX-5": [1290, 195],
            "RS-EX-6": [860, 195],
            "RS-EX-7": [865, 401],
            "RS-EX-8": [1290, 401],
        },
    }

    @classproperty
    def location(cls):
        if datetime.now() > datetime(2024, 12, 29, 4):
            return {"normal": {}, "ex": {}}
        return cls._location

    def generate_names(self):
        names = {}
        font_size = 37 if self.difficulty == "ex" else 40
        for name in self._location[self.difficulty].keys():
            names[name] = generate_name(name, font_size, pad_right=10)
        self.names = names

    def run(
        self,
        name: str,
        mode: Literal["auto", "copy"] = "auto",
        switch_to_ex: bool = False,
    ) -> None:
        logger.info("导航至活动关卡")
        self.switch_to_ex = switch_to_ex  # 是否切换到突袭模式
        self.difficulty = "ex" if "-EX-" in name else "normal"
        self.name = name
        self.mode = mode
        self.generate_names()
        super().run()
        return True

    def transition(self) -> bool:
        if (scene := self.scene()) == Scene.TERMINAL_MAIN:
            self.terminal_entry("navigation/activity/terminal.jpg")
        elif scene == Scene.ACTIVITY_MAIN:
            self.tap(f"navigation/activity/entry_{self.difficulty}")
        elif scene in [
            Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL,
            Scene.ACTIVITY_EX_CHOOSE_LEVEL,
        ]:
            if (
                self.mode == "copy"
                and (result := config.recog.match("story_stage"))
                and result[0] > 0.8
            ):
                self.ctap(result[1], 3)
                return

            name, val, loc = None, 1, None
            for n, img in self.names.items():
                result = cv2.matchTemplate(config.recog.gray, img, cv2.TM_SQDIFF_NORMED)
                min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
                if min_val < val:
                    val = min_val
                    loc = min_loc
                    name = n
            logger.debug(f"在{loc}找到关卡{name}")

            target = va(
                vs(loc, self.location[self.difficulty][name]),
                self.location[self.difficulty][self.name],
            )
            if target[0] > 1920:
                self.swipe_ext(
                    [(1400, 540), (400, 540), (400, 800)], [200, 300], 0, 0.1
                )
            elif target[0] < 0:
                self.swipe_ext(
                    [(400, 540), (1400, 540), (1400, 800)], [200, 300], 0, 0.1
                )
            else:
                self.ctap(va(target, (60, 20)), 3)
        elif scene == Scene.OPERATOR_BEFORE:
            if self.find("ope_ex_mode") and self.switch_to_ex:
                self.ctap("ope_ex_mode", 3)
                return

            if self.mode == "auto":
                return True
            elif self.mode == "copy":
                if not self.switch_to_ex:
                    if config.recog.gray[65][1333] < 200:
                        self.sleep()
                        return
                    # 取消代理作战
                    if config.recog.gray[907][1600] > 127 and not self.find(
                        "ope_agency_lock"
                    ):
                        self.ctap((1776, 908), 3)
                        return
                    self.ctap("ope_start", 3)
                else:
                    self.ctap("ope_ex_start", 3)
        elif scene == Scene.OPERATOR_SELECT and self.mode == "copy":
            return True
        elif scene in [Scene.OPERATOR_RECOVER_ORIGINITE, Scene.OPERATOR_RECOVER_POTION]:
            return True
        elif scene == Scene.STORY_STAGE:
            self.tap("start_story")

        else:
            self.scene_graph_step(Scene.TERMINAL_MAIN)
