-- =====================================================================
-- LiveStrat — Bosses.lua
-- Sélecteur d'instance/boss branché sur le JOURNAL DES RENCONTRES :
-- toutes les extensions, tous les donjons et raids, sans aucune donnée
-- à embarquer. Pour chaque boss on retrouve SA carte (l'étage où il vit)
-- et sa position — la tête de mort du journal, posée sur notre tableau.
--
-- AUTO-DÉTECTION : à l'ouverture en instance, le tableau s'ouvre sur
-- l'étage courant du joueur ; au pull (ENCOUNTER_START), il bascule sur
-- le boss engagé.
-- =====================================================================
local ADDON, ns = ...
local L = ns.L

local Bosses = {}
ns.modules.Bosses = Bosses

-- ---------------------------------------------------------------------
-- Lecture du journal (paresseuse + mémoïsée)
-- ---------------------------------------------------------------------
-- instances = { { id, name, raid = bool }, ... } (tier courant d'abord)
function Bosses:Instances()
    if self._instances then return self._instances end
    local out = {}
    pcall(function()
        EJ_SelectTier(EJ_GetNumTiers())   -- extension courante (Midnight)
        for _, isRaid in ipairs({ false, true }) do
            local i = 1
            while true do
                local id, name = EJ_GetInstanceByIndex(i, isRaid)
                if not id then break end
                out[#out + 1] = { id = id, name = name, raid = isRaid }
                i = i + 1
            end
        end
    end)
    self._instances = out
    return out
end

-- Boss d'une instance : { { encID, name, mapID, x, y }, ... }
-- La position vient de GetEncountersOnMap sur chaque étage de la carte
-- d'instance (c'est la source des têtes de mort de la carte officielle).
function Bosses:Encounters(instanceID)
    self._encCache = self._encCache or {}
    if self._encCache[instanceID] then return self._encCache[instanceID] end
    local list = {}
    pcall(function()
        EJ_SelectInstance(instanceID)
        local j = 1
        while true do
            local name, _, encID = EJ_GetEncounterInfoByIndex(j, instanceID)
            if not name then break end
            list[#list + 1] = { encID = encID, name = name }
            j = j + 1
        end
        -- cartes de l'instance : la carte principale + ses étages
        local _, _, _, _, _, _, instMapID = EJ_GetInstanceInfo(instanceID)
        local maps = {}
        if instMapID and instMapID > 0 then
            maps[#maps + 1] = instMapID
            for _, child in ipairs(C_Map.GetMapChildrenInfo(instMapID) or {}) do
                maps[#maps + 1] = child.mapID
            end
        end
        local byEnc = {}
        for _, mapID in ipairs(maps) do
            local pins = C_EncounterJournal
                and C_EncounterJournal.GetEncountersOnMap
                and C_EncounterJournal.GetEncountersOnMap(mapID)
            for _, pin in ipairs(pins or {}) do
                if not byEnc[pin.encounterID] then
                    byEnc[pin.encounterID] = {
                        mapID = mapID, x = pin.mapX, y = pin.mapY,
                    }
                end
            end
        end
        for _, e in ipairs(list) do
            local pos = byEnc[e.encID]
            if pos then
                e.mapID, e.x, e.y = pos.mapID, pos.x, pos.y
            end
        end
    end)
    self._encCache[instanceID] = list
    return list
end

-- L'instance du journal correspondant à LÀ OÙ EST le joueur (auto-détection).
function Bosses:CurrentInstance()
    local id
    pcall(function()
        if IsInInstance() then
            id = EJ_GetInstanceForMap(C_Map.GetBestMapForUnit("player") or 0)
        end
    end)
    if id and id > 0 then
        for _, inst in ipairs(self:Instances()) do
            if inst.id == id then return inst end
        end
        -- instance d'une autre extension : la fabriquer à la volée
        local name = select(1, EJ_GetInstanceInfo(id))
        if name then return { id = id, name = name } end
    end
    return nil
end

-- Boss par encounterID (pour ENCOUNTER_START) — cherche dans l'instance
-- courante d'abord.
function Bosses:FindByEncounterID(encID)
    local inst = self:CurrentInstance()
    if not inst then return nil end
    for _, e in ipairs(self:Encounters(inst.id)) do
        if e.encID == encID then return inst, e end
    end
    -- ENCOUNTER_START donne un DungeonEncounterID, le journal un
    -- journalEncounterID : passerelle officielle par le NOM.
    local jEnc
    pcall(function()
        jEnc = select(1, EJ_GetEncounterInfoByDungeonEncounterID
            and EJ_GetEncounterInfoByDungeonEncounterID(encID))
    end)
    if jEnc then
        for _, e in ipairs(self:Encounters(inst.id)) do
            if e.name == jEnc then return inst, e end
        end
    end
    return inst, nil
end
