--[[
============================================================================
Enhanced Mount Tracker  -  Core/NPCNames.lua
============================================================================
Resolves an npcID to a creature name. MoP Classic has no API to look up an
arbitrary creature's name by ID, so names are gathered the way ATT and ETB
do it — observed from mouseover / target and cached.

Resolution order (first hit wins):
  1. SourceData.BossNames  — baked boss names from Rarity (accurate, instant)
  2. EMT's own runtime cache (EMT_NPCNames, built as you play)
  3. ETB's cache (ETB_RuntimeNPCNames) when Enhanced Transmog Browser is
     installed — a much larger pool, since ETB has been gathering for longer
============================================================================
]]--

local ADDON_NAME, NS = ...
local EMT = NS.EMT
if not EMT then return end

EMT.NPCNames = EMT.NPCNames or {}
local NPC = EMT.NPCNames

NPC._etbDetected = false

-- ----------------------------------------------------------------------------
-- GUID -> npcID
-- ----------------------------------------------------------------------------

local function NPCIDFromGUID(guid)
    if not guid then return nil end
    local kind = strsplit("-", guid)
    if kind ~= "Creature" and kind ~= "Vehicle" then return nil end
    local id = select(6, strsplit("-", guid))
    return id and tonumber(id) or nil
end

-- ----------------------------------------------------------------------------
-- LOOKUP
-- ----------------------------------------------------------------------------

-- Pull a name out of ETB's cache, tolerating both its schema versions:
--   v2: ETB_RuntimeNPCNames[id] = { n = "Name", t = timestamp }
--   v1: ETB_RuntimeNPCNames[id] = "Name"
local function fromETB(npcID)
    local tbl = _G.ETB_RuntimeNPCNames
    if not tbl then return nil end
    local e = tbl[npcID]
    if type(e) == "table" then return e.n end
    if type(e) == "string" then return e end
    return nil
end

-- Returns name(string) or nil.
function NPC:Get(npcID)
    if not npcID then return nil end
    local baked = EMT.BossNames and EMT.BossNames[npcID]
    if baked then return baked end
    local mine = EMT_NPCNames and EMT_NPCNames[npcID]
    if mine then return mine end
    return fromETB(npcID)
end

-- "Boss Name" if known, else a stable "(creature #12345)" placeholder.
function NPC:GetDisplay(npcID)
    if not npcID then return nil end
    return self:Get(npcID) or ("creature #" .. tostring(npcID))
end

function NPC:IsETBDetected()
    return self._etbDetected
end

-- ----------------------------------------------------------------------------
-- RUNTIME CAPTURE
-- ----------------------------------------------------------------------------

local function capture(unit)
    local npcID = NPCIDFromGUID(UnitGUID(unit))
    if not npcID then return end
    if EMT_NPCNames[npcID] then return end
    local name = UnitName(unit)
    if not name or name == "" or name == UNKNOWNOBJECT then return end
    EMT_NPCNames[npcID] = name
end

-- ----------------------------------------------------------------------------
-- INIT
-- ----------------------------------------------------------------------------

EMT:RegisterInit(function()
    EMT_NPCNames = EMT_NPCNames or {}

    -- ETB present? (its SavedVariable will exist once ETB has loaded once)
    NPC._etbDetected = (_G.ETB_RuntimeNPCNames ~= nil)
        or (_G.EnhancedTransmogBrowser ~= nil)
    if NPC._etbDetected then
        EMT:Debug("NPCNames", "ETB detected — using its NPC-name cache too")
    end

    local f = CreateFrame("Frame")
    f:RegisterEvent("UPDATE_MOUSEOVER_UNIT")
    f:RegisterEvent("PLAYER_TARGET_CHANGED")
    f:SetScript("OnEvent", function(_, event)
        if event == "UPDATE_MOUSEOVER_UNIT" then
            capture("mouseover")
        else
            capture("target")
        end
    end)
    NPC._eventFrame = f
end)
