import logging
from os.path import join
import random
import sys
import time

import pyautogui

from .constants import images_dir, summon_config as config
from .components import Button, AppWindow, Mouse


class SummonSelector:
    dialog_ok = Button("ok2.png", config["dialog ok"])
    first_summon_pt = config["first summon cell"]
    logger = logging.getLogger(__name__ + "." + "SummonSelector")

    def __init__(self, names, is_guild_wars=False):
        self.names = names
        self.logger = logging.getLogger(__name__ + "." + SummonSelector.__name__)
        # default summon is the top 1
        self.summon = Button("summon_cell.png", SummonSelector.first_summon_pt)
        self.is_guild_wars = is_guild_wars

    @staticmethod
    def compare(name: str):
        image = SummonSelector.get_summon_image_path(name)
        scroll_times = 3
        scroll_length = 20
        for _ in range(scroll_times):
            # XXX: width divide need to update?
            point = AppWindow.locate_center(image, (0, 0, 1 / 3, 1))
            if point is not None:
                SummonSelector.logger.info(f"found: {name}")
                # move point from image center to cell center before return
                image_to_cell = (160, -13)
                return [loc + move_length for loc, move_length in zip(point, image_to_cell)]

            # Mouse scroll could use directly without selecting app first
            # But if using keyboard space key, app have to be selected first
            pyautogui.scroll(-scroll_length)

        # if not found
        pyautogui.scroll(scroll_length * scroll_times)
        return None

    @staticmethod
    def get_summon_image_path(name: str) -> str:
        """Naming should follow rule, or there is no image path"""
        return join(images_dir, "summons", f"{name.replace(' ', '_')}.png")

    # XXX: refactor - remove flag parameter
    def activate(self, bot_detect=False):
        # wait before summon page is ready
        count = 0
        while True:
            time.sleep(0.5)
            if self.is_guild_wars and count % 10 == 0:
                self.logger.debug("click again")
                Mouse.click_again()
            image = self.get_summon_image_path("hint")
            hint = AppWindow.locate_on(image, (0, 0, 1, 1 / 3))
            if hint is not None:
                self.logger.info("enter summon page")
                break
            count += 1
        time.sleep(random.random() * 0.25)

        if bot_detect:
            confirm_img = join(images_dir, "auth_confirm.png")
            confirm_dialog = AppWindow.locate_on(confirm_img, (0, 0, 1, 1))
            if confirm_dialog is not None:
                for _ in range(10):
                    self.logger.info(">>>> CLICK IT NOW <<<<")
                sys.exit(0)

        self.summon.center_point = self.find_summon_point()
        self.logger.info("click selected summon")
        self.summon.double_click()
        time.sleep(random.random() * 0.25)

        self.wait_dialog_box()

        self.logger.info("click ok")
        SummonSelector.dialog_ok.click()

    def wait_dialog_box(self):
        """Wait before confirm dialog box popup"""
        while True:
            time.sleep(0.5)
            dialog = AppWindow.locate_on(SummonSelector.dialog_ok.path, (1 / 3, 2 / 3, 2 / 3, 1 / 3))
            if dialog is not None:
                self.logger.info("dialog popped up")
                return

    def find_summon_point(self) -> tuple:
        """
        Find summon by using `self.names`.
        If there are no summons, random chose one from top 3 summons.
        """
        for name in self.names:
            point = self.compare(name)
            if point is not None:
                return point

        self.logger.info(f"No {self.names}")
        self.logger.info("Random choose one from top 3 summons")
        return self.random_chose_summon(3)

    @staticmethod
    def random_chose_summon(summon_index: int) -> tuple:
        x, y = SummonSelector.first_summon_pt
        index = random.randint(0, summon_index - 1)
        cell_interval = 129
        return (x, y + cell_interval * index)

import logging
from os.path import join
import random
import sys
import time

import pyautogui

from .constants import images_dir, summon_config as config
from .components import Button, AppWindow, Mouse


class SummonSelector:
    dialog_ok = Button("ok2.png", config["dialog ok"])
    first_summon_pt = config["first summon cell"]
    logger = logging.getLogger(__name__ + "." + "SummonSelector")

    def __init__(self, names, is_guild_wars=False):
        self.names = names
        self.logger = logging.getLogger(__name__ + "." + SummonSelector.__name__)
        # default summon is the top 1
        self.summon = Button("summon_cell.png", SummonSelector.first_summon_pt)
        self.is_guild_wars = is_guild_wars

    @staticmethod
    def compare(name: str):
        image = SummonSelector.get_summon_image_path(name)
        scroll_times = 3
        scroll_length = 20
        for _ in range(scroll_times):
            # XXX: width divide need to update?
            point = AppWindow.locate_center(image, (0, 0, 1 / 3, 1))
            if point is not None:
                SummonSelector.logger.info(f"found: {name}")
                # move point from image center to cell center before return
                image_to_cell = (160, -13)
                return [loc + move_length for loc, move_length in zip(point, image_to_cell)]

            # Mouse scroll could use directly without selecting app first
            # But if using keyboard space key, app have to be selected first
            pyautogui.scroll(-scroll_length)

        # if not found
        pyautogui.scroll(scroll_length * scroll_times)
        return None

    @staticmethod
    def get_summon_image_path(name: str) -> str:
        """Naming should follow rule, or there is no image path"""
        return join(images_dir, "summons", f"{name.replace(' ', '_')}.png")

    # XXX: refactor - remove flag parameter
    def activate(self, bot_detect=False):
        # wait before summon page is ready
        count = 0
        while True:
            time.sleep(0.5)
            if self.is_guild_wars and count % 10 == 0:
                self.logger.debug("click again")
                Mouse.click_again()
            image = self.get_summon_image_path("hint")
            hint = AppWindow.locate_on(image, (0, 0, 1, 1 / 3))
            if hint is not None:
                self.logger.info("enter summon page")
                break
            count += 1
        time.sleep(random.random() * 0.25)

        if bot_detect:
            confirm_img = join(images_dir, "auth_confirm.png")
            confirm_dialog = AppWindow.locate_on(confirm_img, (0, 0, 1, 1))
            if confirm_dialog is not None:
                for _ in range(10):
                    self.logger.info(">>>> CLICK IT NOW <<<<")
                sys.exit(0)

        self.summon.center_point = self.find_summon_point()
        self.logger.info("click selected summon")
        self.summon.double_click()
        time.sleep(random.random() * 0.25)

        self.wait_dialog_box()

        self.logger.info("click ok")
        SummonSelector.dialog_ok.click()

    def wait_dialog_box(self):
        """Wait before confirm dialog box popup"""
        while True:
            time.sleep(0.5)
            dialog = AppWindow.locate_on(SummonSelector.dialog_ok.path, (1 / 3, 2 / 3, 2 / 3, 1 / 3))
            if dialog is not None:
                self.logger.info("dialog popped up")
                return

    def find_summon_point(self) -> tuple:
        """
        Find summon by using `self.names`.
        If there are no summons, random chose one from top 3 summons.
        """
        for name in self.names:
            point = self.compare(name)
            if point is not None:
                return point

        self.logger.info(f"No {self.names}")
        self.logger.info("Random choose one from top 3 summons")
        return self.random_chose_summon(3)

    @staticmethod
    def random_chose_summon(summon_index: int) -> tuple:
        x, y = SummonSelector.first_summon_pt
        index = random.randint(0, summon_index - 1)
        cell_interval = 129
        return (x, y + cell_interval * index)

# default summon is the top 1 # XXX: width divide need to update? # move point from image center to cell center before return # Mouse scroll could use directly without selecting app first # But if using keyboard space key, app have to be selected first # if not found Naming should follow rule, or there is no image path # XXX: refactor - remove flag parameter # wait before summon page is ready Wait before confirm dialog box popup Find summon by using `self.names`.         If there are no summons, random chose one from top 3 summons.