"""Field mappings and search configuration for reference finding.

This module defines which GFF fields should be searched for different types of references,
based on the KotOR findrefs utility functionality. Used by PyKotor reference tools and
Holocron Toolset.
"""

from __future__ import annotations

from pykotor.resource.formats.gff.gff_data import GFFFieldType
from pykotor.resource.type import ResourceType

# Field mappings for script references (ResRef fields that contain script names)
SCRIPT_FIELDS: dict[str, set[str]] = {
    "IFO": {
        "Mod_OnAcquireItem",
        "Mod_OnActivateItem",
        "Mod_OnClientLeave",
        "Mod_OnHeartbeat",
        "Mod_OnLoad",
        "Mod_OnStart",
        "Mod_OnPlrDeath",
        "Mod_OnPlrLvlUp",
        "Mod_OnPlrRest",
        "Mod_OnSpawnBtnDn",
        "Mod_OnUnAqreItem",
        "Mod_OnUsrDefined",
    },
    "ARE": {
        "OnEnter",
        "OnExit",
        "OnHeartbeat",
        "OnUserDefined",
    },
    "UTC": {
        "ScriptHeartbeat",
        "ScriptAttacked",
        "ScriptDamaged",
        "ScriptDeath",
        "ScriptDialogue",
        "ScriptDisturbed",
        "ScriptEndDialogu",
        "ScriptEndRound",
        "ScriptOnNotice",
        "ScriptRested",
        "ScriptSpawn",
        "ScriptSpellAt",
        "ScriptUserDefine",
    },
    "UTD": {
        "OnClick",
        "OnClosed",
        "OnDamaged",
        "OnDeath",
        "OnFailToOpen",
        "OnHeartbeat",
        "OnLock",
        "OnMeleeAttacked",
        "OnOpen",
        "OnSpellCastAt",
        "OnTrapTriggered",
        "OnUnlock",
        "OnUserDefined",
    },
    "UTM": {
        "OnOpenStore",
    },
    "UTP": {
        "OnClosed",
        "OnDamaged",
        "OnDeath",
        "OnDisarm",
        "OnEndDialogue",
        "OnHeartbeat",
        "OnInvDisturbed",
        "OnLock",
        "OnMeleeAttacked",
        "OnOpen",
        "OnSpellCastAt",
        "OnTrapTriggered",
        "OnUnlock",
        "OnUsed",
        "OnUserDefined",
    },
    "UTT": {
        "ScriptHeartbeat",
        "ScriptOnEnter",
        "ScriptOnExit",
        "ScriptUserDefine",
    },
    "DLG": {
        "StartingList",
        "EntryList",
        "ReplyList",
        "EndConversation",
        "EndConverAbort",
        "VO_ResRef",
        "Sound",
    },
}

# Field mappings for tag references (String fields)
TAG_FIELDS: dict[str, set[str]] = {
    "UTC": {"Tag"},
    "UTD": {"Tag"},
    "UTM": {"Tag"},
    "UTP": {"Tag"},
    "UTT": {"Tag"},
    "UTI": {"Tag"},
}

# Field mappings for TemplateResRef references (ResRef fields)
TEMPLATE_RESREF_FIELDS: dict[str, set[str]] = {
    "UTC": {"TemplateResRef"},
    "UTD": {"TemplateResRef"},
    "UTM": {"TemplateResRef"},
    "UTP": {"TemplateResRef"},
    "UTT": {"TemplateResRef"},
    "UTI": {"TemplateResRef"},
}

# Field mappings for conversation references (ResRef fields)
CONVERSATION_FIELDS: dict[str, set[str]] = {
    "UTC": {"Conversation"},
    "UTD": {"Conversation"},
    "UTP": {"Conversation"},
    "IFO": {"Mod_OnStart"},
}

# Field mappings for ItemList searches (for tag/resref searches in inventory)
ITEMLIST_FIELDS: dict[str, set[str]] = {
    "UTC": {"ItemList", "Equip_ItemList"},
    "UTP": {"ItemList"},
    "UTM": {"ItemList"},
}

# Nested field paths for DLG script searches
DLG_SCRIPT_PATHS: list[tuple[str, str]] = [
    ("StartingList", "Active"),
    ("StartingList", "Active2"),
    ("StartingList", "ParamStrA"),
    ("StartingList", "ParamStrB"),
    ("EntryList", "Script"),
    ("EntryList", "Script2"),
    ("EntryList", "ActionParamStrA"),
    ("EntryList", "ActionParamStrB"),
    ("EntryList", "RepliesList"),
    ("ReplyList", "Script"),
    ("ReplyList", "Script2"),
    ("ReplyList", "ActionParamStrA"),
    ("ReplyList", "ActionParamStrB"),
    ("ReplyList", "EntriesList"),
]

# Nested field paths for DLG reply/entry condition searches
DLG_CONDITION_PATHS: list[tuple[str, str]] = [
    ("EntryList", "RepliesList"),
    ("ReplyList", "EntriesList"),
]

# Field types to search for each reference type
SCRIPT_FIELD_TYPES: set[GFFFieldType] = {GFFFieldType.ResRef}
TAG_FIELD_TYPES: set[GFFFieldType] = {GFFFieldType.String}
TEMPLATE_RESREF_FIELD_TYPES: set[GFFFieldType] = {GFFFieldType.ResRef}
CONVERSATION_FIELD_TYPES: set[GFFFieldType] = {GFFFieldType.ResRef}
ITEMLIST_FIELD_TYPES: set[GFFFieldType] = {GFFFieldType.String, GFFFieldType.ResRef}


def get_script_fields_for_type(file_type: str) -> set[str]:
    """Get script field names for a specific GFF file type."""
    return SCRIPT_FIELDS.get(file_type, set())


def get_tag_fields_for_type(file_type: str) -> set[str]:
    """Get tag field names for a specific GFF file type (includes ItemList for UTC/UTP/UTM)."""
    fields = TAG_FIELDS.get(file_type, set()).copy()
    if file_type in {"UTC", "UTP", "UTM"}:
        fields.update(ITEMLIST_FIELDS.get(file_type, set()))
    return fields


def get_template_resref_fields_for_type(file_type: str) -> set[str]:
    """Get TemplateResRef field names for a specific GFF file type."""
    return TEMPLATE_RESREF_FIELDS.get(file_type, set())


def get_conversation_fields_for_type(file_type: str) -> set[str]:
    """Get conversation field names for a specific GFF file type."""
    return CONVERSATION_FIELDS.get(file_type, set())


def get_itemlist_fields_for_type(file_type: str) -> set[str]:
    """Get ItemList field names for a specific GFF file type."""
    return ITEMLIST_FIELDS.get(file_type, set())


def get_all_searchable_file_types() -> set[str]:
    """All file type abbreviations that can be searched for references (from ResourceType)."""
    result: set[str] = set()
    for restype in ResourceType:
        if restype == ResourceType.INVALID or not restype.extension:
            continue
        result.add(restype.extension.upper())
    return result
