import time
import os
import numpy as np
import keyboard
import template_finder
from config import Config
from screen import grab
from ui_manager import ScreenObjects, center_mouse, is_visible, wait_until_hidden
from utils.misc import color_filter, wait
from logger import Logger
from utils.custom_mouse import mouse
from math import sqrt

class Npc:
    #A1
    KASHYA = "kashya"
    CHARSI = "charsi"
    AKARA = "akara"
    CAIN = "cain"
    #A2
    FARA = "fara"
    DROGNAN = "droganan"
    LYSANDER = "lysander"
    #A3
    ORMUS = "ormus"
    #A4
    TYRAEL = "tyrael"
    JAMELLA = "jamella"
    HALBU = "halbu"
    #A5
    QUAL_KEHK = "qual_kehk"
    MALAH = "malah"
    LARZUK = "larzuk"
    ANYA = "anya"

npcs = {
    Npc.QUAL_KEHK: {
        "name_tag_white": color_filter(template_finder.get_template("QUAL_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("QUAL_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "resurrect": {
                "white": color_filter(template_finder.get_template("RESURRECT"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("RESURRECT_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["QUAL_0", "QUAL_45", "QUAL_45_B", "QUAL_90", "QUAL_135", "QUAL_135_B", "QUAL_135_C", "QUAL_180", "QUAL_180_B", "QUAL_225", "QUAL_225_B", "QUAL_270", "QUAL_315"],
        "roi": [225, 57, (850-225), (442-57)],
        "poses": [[350, 140], [310, 268], [385, 341], [481, 196], [502, 212], [771, 254]]
    },
    Npc.MALAH: {
        "name_tag_white": color_filter(template_finder.get_template("MALAH_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("MALAH_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["MALAH_FRONT", "MALAH_BACK", "MALAH_45", "MALAH_SIDE", "MALAH_SIDE_2"],
        "roi": [383, 193, (762-383), (550-193)],
        "poses": [[445, 485], [526, 473], [602, 381], [623, 368], [641, 323], [605, 300], [622, 272], [638, 284], [677, 308], [710, 288]]
    },
    Npc.LARZUK: {
        "name_tag_white": color_filter(template_finder.get_template("LARZUK_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("LARZUK_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade_repair": {
                "white": color_filter(template_finder.get_template("TRADE_REPAIR"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_REPAIR_BLUE"), Config().colors["blue"])[1],
            }
        },
        "roi": [570, 70, (1038-570), (290-70)],
        "template_group": ["LARZUK_FRONT", "LARZUK_BACK", "LARZUK_SIDE", "LARZUK_SIDE_2", "LARZUK_SIDE_3"],
        "poses": [[733, 192], [911, 143]]
    },
    Npc.ANYA: {
        "name_tag_white": color_filter(template_finder.get_template("ANYA_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("ANYA_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["ANYA_FRONT", "ANYA_BACK", "ANYA_SIDE"]
    },
    Npc.TYRAEL: {
        "name_tag_white": color_filter(template_finder.get_template("TYRAEL_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("TYRAEL_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "resurrect": {
                "white": color_filter(template_finder.get_template("RESURRECT"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("RESURRECT_BLUE"), Config().colors["blue"])[1],
            }
        },
        "roi": [569, 86, (852-569), (357-86)],
        "template_group": ["TYRAEL_1", "TYRAEL_2"]
    },
    Npc.ORMUS: {
        "name_tag_white": color_filter(template_finder.get_template("ORMUS_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("ORMUS_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "roi": [444, 13, (816-444), (331-13)],
        "poses": [[526, 131], [602, 192], [698, 218], [756, 188]],
        "template_group": ["ORMUS_0", "ORMUS_1", "ORMUS_2", "ORMUS_3", "ORMUS_4", "ORMUS_5"]
    },
    Npc.FARA: {
        "name_tag_white": color_filter(template_finder.get_template("FARA_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("FARA_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade_repair": {
                "white": color_filter(template_finder.get_template("TRADE_REPAIR"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_REPAIR_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["FARA_LIGHT_1", "FARA_LIGHT_2", "FARA_LIGHT_3", "FARA_LIGHT_4", "FARA_LIGHT_5", "FARA_LIGHT_6", "FARA_LIGHT_7", "FARA_LIGHT_8", "FARA_LIGHT_9", "FARA_MEDIUM_1", "FARA_MEDIUM_2", "FARA_MEDIUM_3", "FARA_MEDIUM_4", "FARA_MEDIUM_5", "FARA_MEDIUM_6", "FARA_MEDIUM_7", "FARA_DARK_1", "FARA_DARK_2", "FARA_DARK_3", "FARA_DARK_4", "FARA_DARK_5", "FARA_DARK_6", "FARA_DARK_7"]
    },
    Npc.DROGNAN: {
        "name_tag_white": color_filter(template_finder.get_template("DROGNAN_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("DROGNAN_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["DROGNAN_FRONT", "DROGNAN_LEFT", "DROGNAN_RIGHT_SIDE"]
    },
    Npc.LYSANDER: {
        "name_tag_white": color_filter(template_finder.get_template("LYSANDER_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("LYSANDER_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["LYSANDER_FRONT", "LYSANDER_BACK", "LYSANDER_SIDE", "LYSANDER_SIDE_2"]
    },
    Npc.CAIN: {
        "name_tag_white": color_filter(template_finder.get_template("CAIN_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("CAIN_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "identify": {
                "white": color_filter(template_finder.get_template("IDENTIFY"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("IDENTIFY_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["CAIN_0", "CAIN_1", "CAIN_2", "CAIN_3"]
    },
    Npc.JAMELLA: {
        "name_tag_white": color_filter(template_finder.get_template("JAMELLA_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("JAMELLA_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            },
            "gamble": {
                "white": color_filter(template_finder.get_template("GAMBLE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("GAMBLE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["JAMELLA_FRONT", "JAMELLA_BACK", "JAMELLA_SIDE", "JAMELLA_SIDE_2", "JAMELLA_SIDE_3", "JAMELLA_DRAWING"]
    },
    Npc.HALBU: {
        "name_tag_white": color_filter(template_finder.get_template("HALBU_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("HALBU_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade_repair": {
                "white": color_filter(template_finder.get_template("TRADE_REPAIR"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_REPAIR_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["HALBU_FRONT", "HALBU_BACK", "HALBU_SIDE", "HALBU_SIDE_2"]
    },
    Npc.AKARA: {
        "name_tag_white": color_filter(template_finder.get_template("AKARA_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("AKARA_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade": {
                "white": color_filter(template_finder.get_template("TRADE"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_BLUE"), Config().colors["blue"])[1],
            }
        },
        "roi": [603, 176, (1002-603), (478-176)],
        "poses": [[692, 377], [834, 378], [948, 345], [867, 290], [696, 317]],
        "template_group": ["AKARA_FRONT", "AKARA_BACK", "AKARA_SIDE", "AKARA_SIDE_2"]
    },
    Npc.CHARSI: {
        "name_tag_white": color_filter(template_finder.get_template("CHARSI_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("CHARSI_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "trade_repair": {
                "white": color_filter(template_finder.get_template("TRADE_REPAIR"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("TRADE_REPAIR_BLUE"), Config().colors["blue"])[1],
            }
        },
        "roi": [249, 76, (543-249), (363-76)],
        "poses": [[331, 227], [368, 284], [484, 174]],
        "template_group": ["CHARSI_FRONT", "CHARSI_BACK", "CHARSI_SIDE", "CHARSI_SIDE_2", "CHARSI_SIDE_3"]
    },
    Npc.KASHYA: {
        "name_tag_white": color_filter(template_finder.get_template("KASHYA_NAME_TAG_WHITE"), Config().colors["white"])[1],
        "name_tag_gold": color_filter(template_finder.get_template("KASHYA_NAME_TAG_GOLD"), Config().colors["gold"])[1],
        "action_btns": {
            "resurrect": {
                "white": color_filter(template_finder.get_template("RESURRECT"), Config().colors["white"])[1],
                "blue": color_filter(template_finder.get_template("RESURRECT_BLUE"), Config().colors["blue"])[1],
            }
        },
        "template_group": ["KASHYA_FRONT", "KASHYA_BACK", "KASHYA_SIDE", "KASHYA_SIDE_2"]
    }
}


def escape_dialogue(img) -> np.ndarray:
    while is_visible(ScreenObjects.NPCDialogue, img):
        keyboard.send("esc")
        if wait_until_hidden(ScreenObjects.NPCDialogue, 0.5):
            break
        img = grab()
    return img

def open_npc_menu(npc_key: Npc) -> bool:
    global npcs
    roi = Config().ui_roi["cut_skill_bar"]
    roi_npc_search = Config().ui_roi["search_npcs"]
    # Search for npc name tags by hovering to all template locations that are found
    start = time.time()
    attempts = 0
    while (time.time() - start) < 35:
        img = grab()
        results = []
        for key in npcs[npc_key]["template_group"]:
            if attempts == 0 and "roi" in npcs[npc_key] and (time.time() - start) < 6:
                roi_npc = npcs[npc_key]["roi"]
            else:
                roi_npc = roi_npc_search
            res = template_finder.search(key, img, threshold=0.35, roi=roi_npc)
            if res.valid:
                is_unique = True
                for r in results:
                    if (abs(r["pos"][0] - res.center_monitor[0]) + abs(r["pos"][1] - res.center_monitor[1])) < 22:
                        is_unique = False
                        break
                if is_unique:
                    min_dist=10000
                    if attempts == 0 and "poses" in npcs[npc_key]:
                        # find distance between template match and nearest pose (([x2] - x1)**2 + (y2 - y1)**2)
                        for pose in npcs[npc_key]["poses"]:
                            dist = sqrt((res.center_monitor[0] - pose[0])**2 + (res.center_monitor[1] - pose[1])**2)
                            min_dist = dist if dist < min_dist else min_dist
                    results.append({"pos": res.center_monitor, "score": res.score, "combo": min_dist / (res.score**2)})
        # sort by composite of template match score and distance to NPC pose
        results = sorted(results, key=lambda r: r["combo"])
        for result in results:
            mouse.move(*result["pos"], randomize=3, delay_factor=[0.3, 0.5])
            wait(0.2, 0.3)
            img = grab()
            img = escape_dialogue(img)
            _, filtered_inp_w = color_filter(img, Config().colors["white"])
            _, filtered_inp_g = color_filter(img, Config().colors["gold"])
            res_w = template_finder.search(npcs[npc_key]["name_tag_white"], filtered_inp_w, 0.9, roi=roi).valid
            res_g = template_finder.search(npcs[npc_key]["name_tag_gold"], filtered_inp_g, 0.9, roi=roi).valid
            if res_w:
                mouse.click(button="left")
                attempts += 1
                wait(0.7, 1.0)
                _, filtered_inp = color_filter(grab(), Config().colors["gold"])
                res = template_finder.search(npcs[npc_key]["name_tag_gold"], filtered_inp, 0.9, roi=roi).valid
                if res:
                    return True
            elif res_g:
                return True
    return False

def press_npc_btn(npc_key: Npc, action_btn_key: str):
    global npcs
    img = grab()
    img = escape_dialogue(img)
    _, filtered_inp_w = color_filter(img, Config().colors["white"])
    res = template_finder.search(
        npcs[npc_key]["action_btns"][action_btn_key]["white"],
        filtered_inp_w, 0.85, roi=Config().ui_roi["cut_skill_bar"]
    )
    if not res.valid and "blue" in npcs[npc_key]["action_btns"][action_btn_key]:
        # search for highlighted / blue action btn
        _, filtered_inp_b = color_filter(img, Config().colors["blue"])
        res = template_finder.search(
            npcs[npc_key]["action_btns"][action_btn_key]["blue"],
            filtered_inp_b, 0.85, roi=Config().ui_roi["cut_skill_bar"]
        )
    if res.valid:
        mouse.move(*res.center_monitor, randomize=3, delay_factor=[1.0, 1.5])
        wait(0.2, 0.4)
        mouse.click(button="left")
        wait(0.04, 0.08)
        center_mouse()
    else:
        Logger.error(f"Could not find {action_btn_key} btn. Should not happen! Continue...")
        keyboard.send("esc")


# Testing: Stand close to Qual-Kehk or Malah and run
if __name__ == "__main__":
    from screen import grab
    from config import Config
    import os
    import keyboard
    keyboard.add_hotkey('f12', lambda: os._exit(1))
    keyboard.wait("f11")
    open_npc_menu(Npc.MALAH)
