import math
from copy import deepcopy

import cv2

from mower.data import agent_list
from mower.utils import config
from mower.utils.character_recognize import (
    match_portrait,
    operator_team_select,
)
from mower.utils.graph.utils import SceneGraphSolver
from mower.utils.log import logger
from mower.utils.scene import Scene

from .choose_skill import ChooseSkillSolver


class BattleAgentChooseSolver(SceneGraphSolver):
    def run(self, agents: list) -> None:
        if agents == []:
            raise ValueError("干员列表为空")
        self.agents = agents
        self.agents_copy = deepcopy(agents)
        self.cleard = False
        self.filter = False
        self.agent = None
        self.choosed = []
        self.final_check = False
        self.check = []
        self.lack = []
        self.tmp_data = {}
        self.swipe_time = 0
        self.success = False

        super().run()
        return self.lack

    def choose_agents(self):
        if self.final_check:
            if pos := self.find("choose_agent/foldup"):
                self.tap(pos, interval=0.1)
                return
            check = self.get_agent_pos()
            if check:
                for i in check:
                    if i in self.choosed:
                        self.check.append(i)
                if (len(self.check) + len(self.lack)) == len(self.agents):
                    return True
                elif (len(self.check) + len(self.lack)) < len(self.agents):
                    self.swipe_noinertia((1000, 540), (-1900, 0))
                    return
            else:
                logger.error(f"{self.choosed-self.check} 确认失败")
                return False

        if pos := self.find("choose_agent/open_profession"):
            self.tap(pos, interval=0.1)

        if self.cleard is False:
            if self.find("choose_agent/battle_empty"):
                self.cleard = True
            else:
                self.tap_element("choose_agent/clear_battle", interval=0.1)
                return

        if self.agent is None:
            if len(self.agents_copy) > 0:
                self.agent = self.agents_copy.pop(0)
            else:
                self.final_check = True
                self.tag_choosed()
                return
        elif self.agent["name"] not in self.choosed:
            now_choose = self.get_agent_pos()
            if self.agent["name"] in now_choose:
                ChooseSkillSolver().run(self.agent["skill"])
                self.choosed.append(self.agent["name"])

                if len(self.agents_copy) > 0:
                    tmp = self.agents_copy.pop(0)
                else:
                    self.final_check = True
                    self.tag_choosed()
                    return

                if "opers" in tmp:
                    tag = agent_list[tmp["opers"][-1]["name"]]["profession"]
                else:
                    tag = agent_list[tmp["name"]]["profession"]

                if agent_list[self.agent["name"]]["profession"] == tag:
                    self.tag_choosed()
                self.tag_choosed(tag)

                self.agent = tmp
                config.recog.update()

        agents = dict(operator_team_select(config.recog.img))
        if "opers" in self.agent:
            for i in self.agent["opers"]:
                if i["name"] in agents.keys():
                    self.agent = i
                    self.tap(agents[i["name"]], interval=0.2)
                    return
        else:
            try:
                self.tap(agents[self.agent["name"]], interval=0.2)
                return
            except KeyError:
                if self.tag_choosed(agent_list[self.agent["name"]]["profession"]):
                    return

        if set(agents.keys()).issubset(self.tmp_data.keys()):
            self.swipe_time = self.swipe_time + 1
            if self.swipe_time > 1:
                logger.error(f"选择干员: {self.agent}失败 滑动次数过多")
                self.lack.append(self.agent)
                self.agent = None
                return
        else:
            self.swipe_time = 0

        self.swipe_noinertia((1000, 540), (-1900, 0))

        self.tmp_data = agents
        return

    def get_agent_pos(self):
        img = cv2.cvtColor(config.recog.img, cv2.COLOR_RGB2HSV)
        img = cv2.inRange(img, (90, 200, 120), (200, 255, 255))
        contours, _ = cv2.findContours(img, cv2.RETR_LIST, cv2.CHAIN_APPROX_SIMPLE)
        segments = []
        for contour in contours:
            if cv2.contourArea(contour) < 40000 or cv2.contourArea(contour) > 100000:
                continue
            # 近似轮廓
            x, y, w, h = cv2.boundingRect(contour)
            current_segment = ((x, y), (x + w, y + h))
            is_close = False
            for segment in segments:
                if (
                    math.sqrt(
                        math.pow(segment[0][0] - current_segment[0][0], 2)
                        + math.pow(segment[0][1] - current_segment[0][1], 2)
                    )
                    < 40
                ):
                    is_close = True
                    break

            # 如果不相近，则添加到列表中
            if not is_close:
                segments.append(current_segment)

        logger.debug(f"segments:{segments}")
        return list(dict(match_portrait(config.recog.gray, segment=segments)).keys())

    def tag_choosed(self, profession: str = "ALL"):
        str = "choose_agent/profession/" + profession
        if pos := self.find(str):
            if arrow := self.find("choose_agent/profession/choose_arrow"):
                if (
                    math.sqrt(
                        math.pow(pos[0][0] - arrow[0][0], 2)
                        + math.pow(pos[0][1] - arrow[0][1], 2)
                    )
                    < 100
                ):
                    return False
                else:
                    self.tap(pos[0], interval=0.2)
                    return True
            else:
                self.tap(pos[0], interval=0.2)
                return True

    def transition(self) -> bool:
        if (scene := self.scene()) == Scene.OPERATOR_AGENT_SELECT:
            if self.choose_agents():
                self.success = True
                self.tap_element("choose_agent/battle_confirm")
        elif scene == Scene.OPERATOR_SELECT:
            if self.success:
                return True
            self.tap_element("choose_agent/fast_select")
        elif scene in self.waiting_scene:
            self.waiting_solver()
        else:
            return False
