PROGRAM_NAME = "Nightreign Armament Helper"
VERSION = "2.3.0"

TEXT_ORIGINS: list[int] = [
    TEXT_ORIGIN_NONE := 0,
    TEXT_ORIGIN_OCR := 1,
    TEXT_ORIGIN_PIXELSET := 3,
]

MATCH_RESULTS: list[int] = [
    NO_MATCH := 0,
    GOOD_MATCH := 1,
    PERFECT_MATCH := 2,
]

BUTTON_TYPES = [
    CONFIRM := "confirm",
    CLOSE := "close",
]
BUTTON_GEOMETRY_TYPES = [
    KEYBOARD_BUTTON_GEOMETRY := "kb",
    GAMEPAD_BUTTON_GEOMETRY := "gp",
]
CONTROLLER_TYPES_BY_BUTTON_GEOMETRY = {
    KEYBOARD_BUTTON_GEOMETRY: [
        KEYBOARD := "kb",
    ],
    GAMEPAD_BUTTON_GEOMETRY: [
        GENERIC_GAMEPAD := "gp",
        DUALSHOCK4 := "ds4",
        DUALSENSE := "ds5",
    ],
}

BUTTON_COORDINATES_4K = {  # Values for 4K resolution (3840x2160)
    KEYBOARD_BUTTON_GEOMETRY: (1997, 1997 + 64, 97, 97 + 64),
    GAMEPAD_BUTTON_GEOMETRY: (2001, 2001 + 56, 101, 101 + 56),
}

RECLUSE_ELEMENT_COORDINATES_4K = {  # Values for 4K resolution (3840x2160)
    1: (1873, 1873 + 51, 1644, 1644 + 51),  # Element 1
    2: (2035, 2035 + 52, 1725, 1725 + 52),  # Element 2
    3: (2033, 2033 + 52, 1563, 1563 + 52),  # Element 3
}

UI_IDENTIFIERS = [
    ARMAMENT_DETECTION_DEFAULT := "armament_detection_default",
    ARMAMENT_DETECTION_DEFAULT_REPLACE := "armament_detection_default_replace",
    ARMAMENT_DETECTION_BOSS_DROP := "armament_detection_boss_drop",
    ARMAMENT_DETECTION_SHOP := "armament_detection_shop",
    MENU_DETECTION := "menu_detection",
    CHARACTER_DETECTION := "character_detection",
    CHARACTER_DROPDOWN := "character_dropdown",
]
ARMAMENT_DETECTION_IDS = [
    ARMAMENT_DETECTION_DEFAULT,
    ARMAMENT_DETECTION_DEFAULT_REPLACE,
    ARMAMENT_DETECTION_BOSS_DROP,
    ARMAMENT_DETECTION_SHOP,
]
# Thresholds for Jaccard similarity when matching text
TEXT_SIMILARITY_THRESHOLDS = {
    ARMAMENT_DETECTION_DEFAULT: 0.85,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 0.85,
    ARMAMENT_DETECTION_BOSS_DROP: 0.85,
    ARMAMENT_DETECTION_SHOP: 0.85,
    MENU_DETECTION: 0.75,
    CHARACTER_DETECTION: 0.90,
}
# How many pixels in the detection box must be white to even consider calling the OCR
OCR_MINIMUM_PIXELS_PERCENTS = {
    ARMAMENT_DETECTION_DEFAULT: 0.0025,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 0.0025,
    ARMAMENT_DETECTION_BOSS_DROP: 0.0025,
    ARMAMENT_DETECTION_SHOP: 0.0025,
    MENU_DETECTION: 0.0025,
    CHARACTER_DETECTION: 0.0025,
}
# Accepted false negative rate when matching pixel sets ((100-x)% of the white pixels must match)
PIXELSET_FN_RATES = {
    ARMAMENT_DETECTION_DEFAULT: 0.1,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 0.1,
    ARMAMENT_DETECTION_BOSS_DROP: 0.1,
    ARMAMENT_DETECTION_SHOP: 0.1,
    MENU_DETECTION: 0.10,
    CHARACTER_DETECTION: 0.05,
}
# Accepted false positive rate when matching pixel sets ((100-x)% of the black pixels must match)
PIXELSET_FP_RATES = {
    ARMAMENT_DETECTION_DEFAULT: 0.50,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 0.50,
    ARMAMENT_DETECTION_BOSS_DROP: 0.50,
    ARMAMENT_DETECTION_SHOP: 0.50,
    MENU_DETECTION: 0.80,
    CHARACTER_DETECTION: 0.10,
}
# Threshold from 0 - 255, higher means a cleaner image, but less info to match
PIXELSET_THRESHOLDS = {
    ARMAMENT_DETECTION_DEFAULT: 190,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 190,
    ARMAMENT_DETECTION_BOSS_DROP: 190,
    ARMAMENT_DETECTION_SHOP: 190,
    MENU_DETECTION: 200,
    CHARACTER_DETECTION: 200,
}
# Threshold reduction for comparison, higher means more lenient matching
PIXELSET_THRESHOLD_REDUCTIONS = {
    ARMAMENT_DETECTION_DEFAULT: 5,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 5,
    ARMAMENT_DETECTION_BOSS_DROP: 5,
    ARMAMENT_DETECTION_SHOP: 5,
    MENU_DETECTION: 10,
    CHARACTER_DETECTION: 0,
}
# Time in seconds between detection checks
MINIMUM_TIME_BETWEEN_SCREENGRABS = 0.1

DETECTION_LOOP_PERIODS = {
    ARMAMENT_DETECTION_DEFAULT: 0.2,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 0.2,
    MENU_DETECTION: 0.5,
    CHARACTER_DETECTION: 0.2,
}

OCR_THRESHOLDS = {
    ARMAMENT_DETECTION_DEFAULT: 115,
    ARMAMENT_DETECTION_DEFAULT_REPLACE: 115,
    ARMAMENT_DETECTION_BOSS_DROP: 115,
    ARMAMENT_DETECTION_SHOP: 115,
    MENU_DETECTION: 170,
    CHARACTER_DETECTION: 140,
}

TESSERACT_CONFIG = f"--oem 3 --psm 7 -c language_model_penalty_non_freq_dict_word=1 -c language_model_penalty_non_dict_word=1 -c tessedit_do_invert=0"
TESSERACT_TIMEOUT = 2  # seconds

NO_CHARACTER = "_____"

MENU_STATES: list[str] = [
    MENU_STATE_DEFAULT := "DEFAULT",
    MENU_STATE_SHOP := "SHOP",
    MENU_STATE_DORMANT_POWER := "DORMANT_POWER",
]

REPLACE_ARMAMENT_REL_POS_TO_NAME = 0.3281
DETECTION_BOXES = {
    # (top, bottom, left, right)
    ARMAMENT_DETECTION_DEFAULT: (0.2833, 0.3133, 0.3800, 0.5800),
    ARMAMENT_DETECTION_DEFAULT_REPLACE: (0.2833, 0.3133, 0.3800 + REPLACE_ARMAMENT_REL_POS_TO_NAME, 0.5800 + REPLACE_ARMAMENT_REL_POS_TO_NAME),
    ARMAMENT_DETECTION_BOSS_DROP: (0.2722, 0.3055, 0.4820, 0.6820),
    ARMAMENT_DETECTION_SHOP: (0.2555, 0.2889, 0.400, 0.600),
    MENU_DETECTION: (0.1278, 0.2000, 0.0700, 0.1800),
    CHARACTER_DETECTION: (0.2000, 0.2389, 0.1250, 0.2400),
}


UI_ELEMENT_POSITIONS = {
    # (x, y) in relative coordinates
    ARMAMENT_DETECTION_DEFAULT: (0.314, 0.2444),
    ARMAMENT_DETECTION_BOSS_DROP: (0.417, 0.2355),
    ARMAMENT_DETECTION_SHOP: (0.334, 0.22),
    CHARACTER_DROPDOWN: (0.085, 0.0944),
}


# Button Colors
BUTTON_ENABLED_COLOR = "#4CAF50"  # Green
BUTTON_ENABLED_ACTIVE_COLOR = "#45A049"  # Darker green
BUTTON_DISABLED_COLOR = "#F44336"  # Red
BUTTON_DISABLED_ACTIVE_COLOR = "#D32F2F"  # Darker red
BUTTON_QUIT_COLOR = "#40627C"  # Moonlight blue
BUTTON_QUIT_ACTIVE_COLOR = "#304A5C"  # Darker blue


DEFAULT_LANGUAGE: str = "engus"

LANGUAGES: list[str] = [
    "araae",
    "deude",
    "engus",
    "frafr",
    "itait",
    "jpnjp",
    "korkr",
    "polpl",
    "porbr",
    "rusru",
    "spaar",
    "spaes",
    "thath",
    "zhocn",
    "zhotw",
]

TESSDATA_DOWNLOAD_BASE_URL = "https://raw.githubusercontent.com/tesseract-ocr/tessdata/refs/heads/main/{language}.traineddata"

TESSERACT_LANGUAGES: dict[str, str] = {
    "araae": "ara",
    "deude": "deu",
    "engus": "eng",
    "frafr": "fra",
    "itait": "ita",
    "jpnjp": "jpn",
    "korkr": "kor",
    "polpl": "pol",
    "porbr": "por",
    "rusru": "rus",
    "spaar": "spa",
    "spaes": "spa",
    "thath": "tha",
    "zhocn": "chi_sim",
    "zhotw": "chi_tra",
}

DORMANT_POWER_LANGUAGES: dict[str, str] = {
    "araae": "ﻗﻭة اﻟﺧﻣﻭد",
    "deude": "Schlummernde Kraft",
    "engus": "Dormant Power",
    "frafr": "Puissance cachée",
    "itait": "Potere dormiente",
    "jpnjp": "潜在する力",
    "korkr": "잠재한 힘",
    "polpl": "Drzemiąca siła",
    "porbr": "Poder adormecido",
    "rusru": "Скрытая мощь",
    "spaar": "Poder latente",
    "spaes": "Poder latente",
    "thath": "พลัง​แฝง",
    "zhocn": "潜在能力",
    "zhtw": "潛在能力",
}

SHOP_LANGUAGES: dict[str, str] = {
    "araae": "اﻟﻣﺗﺟﺭ",
    "deude": "Laden",
    "engus": "Shop",
    "frafr": "Boutique",
    "itait": "Negozio",
    "jpnjp": "ショップ",
    "korkr": "상점",
    "polpl": "Sklep",
    "porbr": "Loja",
    "rusru": "Магазин",
    "spaar": "Tienda",
    "spaes": "Tienda",
    "thath": "ร้าน​ค้า",
    "zhocn": "商店",
    "zhtw": "商店",
}
