-- Class icon auras (Midnight).
-- Mirrors Blizzard's arena DebuffFrame CC icon + cooldown swipe onto our class portrait.

local AC = _G.ArenaCore
if not AC then return end

if not (AC.Midnight and AC.Midnight.isMidnight) then return end

local ClassIconAuras = {}
AC.ClassIconAuras = ClassIconAuras

local MAX_ARENA_ENEMIES = 3

ClassIconAuras.initialized = false
ClassIconAuras.hookedFrames = {}
ClassIconAuras.ccActive = {}

-- Check if class icon auras are disabled.
local function IsDisabled()
    local db = AC.DB and AC.DB.profile
    return db and db.classIcons and db.classIcons.showAuras == false
end

local function IsSpiralGlowLineEnabled()
    local db = AC.DB and AC.DB.profile
    if not (db and db.classIcons) then return true end
    return db.classIcons.spiralGlowLine ~= false
end

-- Restore class icon after CC ends.
local function RestoreClassIcon(arenaIndex, classIcon, acFrame)
    classIcon.ccActive = false
    ClassIconAuras.ccActive[arenaIndex] = false
    if classIcon.auraCooldown then
        classIcon.auraCooldown:Clear()
    end

    local db = AC.DB and AC.DB.profile
    local showSpecInstead = db and db.classIcons and db.classIcons.showSpecInstead == true
    if showSpecInstead and acFrame and acFrame.specID and GetSpecializationInfoByID then
        local _, _, _, specIcon = GetSpecializationInfoByID(acFrame.specID)
        if specIcon and classIcon.icon and classIcon.icon.SetTexture then
            classIcon.icon:SetTexture(specIcon)
            if classIcon.icon.SetTexCoord then
                classIcon.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
            end
        end
        if classIcon.overlay and classIcon.overlay.SetTexture then
            classIcon.overlay:SetTexture("Interface\\AddOns\\ArenaCore\\Media\\Classicons\\Overlays\\orangeoverlay.tga")
        end
        return
    end

    local storedClass = acFrame.class
    if storedClass and classIcon.UpdateClassIcon then
        classIcon.UpdateClassIcon(storedClass)
    end
end

function ClassIconAuras:HookDebuffFrame(arenaIndex)
    local _, instanceType = IsInInstance()
    if instanceType ~= "arena" then return end
    if IsActiveBattlefieldArena and not IsActiveBattlefieldArena() then return end
    if self.hookedFrames[arenaIndex] then return end

    local blizzArenaFrame = _G["CompactArenaFrameMember" .. arenaIndex]
    if not blizzArenaFrame then return end

    local debuffFrame = blizzArenaFrame.DebuffFrame
    if not debuffFrame then return end

    local MFM = AC.MasterFrameManager
    local acFrame = MFM and MFM.frames and MFM.frames[arenaIndex]
    if not acFrame then return end

    local classIcon = acFrame.classIcon
    if not classIcon then return end

    -- Cooldown overlay: swipe + numbers.
    local okCooldown, cooldownOrErr = pcall(function()
        local cd = CreateFrame("Cooldown", nil, classIcon, "CooldownFrameTemplate")
        if cd.SetHideCountdownNumbers then
            cd:SetHideCountdownNumbers(false)
        end
        local r = { cd:GetRegions() }
        for i = 1, #r do
            local region = r[i]
            if region and region.GetObjectType and region:GetObjectType() == "FontString" and region.SetFont then
                region:SetFont("Fonts\\FRIZQT__.TTF", 14, "OUTLINE")
            end
        end
        local anchor = classIcon.icon or classIcon
        cd:ClearAllPoints()
        cd:SetAllPoints(anchor)
        cd:SetDrawEdge(IsSpiralGlowLineEnabled())
        cd:SetDrawBling(false)
        cd:SetReverse(false)
        if cd.SetUseCircularEdge then
            cd:SetUseCircularEdge(true)
        end
        if cd.SetSwipeColor then
            cd:SetSwipeColor(0, 0, 0, 0.75)
        end
        return cd
    end)
    classIcon.auraCooldown = okCooldown and cooldownOrErr or nil

    -- Hook 1: mirror CC texture.
    -- Blizzard swaps the icon back to the question mark when CC ends.
    if debuffFrame.Icon then
        hooksecurefunc(debuffFrame.Icon, "SetTexture", function(_, tex)
            if IsDisabled() then
                if classIcon.ccActive then
                    RestoreClassIcon(arenaIndex, classIcon, acFrame)
                end
                return
            end
            if tex == "INTERFACE\\ICONS\\INV_MISC_QUESTIONMARK.BLP" then
                -- CC ended.
                RestoreClassIcon(arenaIndex, classIcon, acFrame)
            else
                -- CC active.
                classIcon.ccActive = true
                ClassIconAuras.ccActive[arenaIndex] = true
                if classIcon.icon then
                    classIcon.icon:SetTexture(tex)
                end
            end
        end)
    end

    -- Hook 2: mirror cooldown swipe + a safety net when it finishes.
    if debuffFrame.Cooldown then
        hooksecurefunc(debuffFrame.Cooldown, "SetCooldown", function()
            if IsDisabled() or not classIcon.auraCooldown then return end
            -- Midnight 12.0+: SetCooldown args are secret, so we query C_LossOfControl
            -- directly. priority is NeverSecret so comparisons are safe. The duration
            -- object API is the approved path that bypasses secret number restrictions.
            local unitToken = "arena" .. arenaIndex
            local count = C_LossOfControl.GetActiveLossOfControlDataCountByUnit(unitToken)
            local bestPriority, bestIndex = -1, nil
            for i = 1, count do
                local data = C_LossOfControl.GetActiveLossOfControlDataByUnit(unitToken, i)
                if data and data.priority > bestPriority then
                    bestPriority = data.priority
                    bestIndex = i
                end
            end
            if bestIndex then
                local durationObj = C_LossOfControl.GetActiveLossOfControlDuration(unitToken, bestIndex)
                if durationObj then
                    -- Avoid IsZero() here: it can produce a secret boolean in Midnight.
                    -- SetCooldownFromDurationObject(clearIfZero=true) handles clearing.
                    pcall(classIcon.auraCooldown.SetCooldownFromDurationObject, classIcon.auraCooldown, durationObj, true)
                    if classIcon.auraCooldown.SetHideCountdownNumbers then
                        classIcon.auraCooldown:SetHideCountdownNumbers(false)
                    end
                end
            end
        end)
        debuffFrame.Cooldown:HookScript("OnCooldownDone", function()
            if classIcon.ccActive then
                RestoreClassIcon(arenaIndex, classIcon, acFrame)
            end
        end)
    end

    -- Safety net: on Retail, Blizzard doesn't always swap the icon back to question mark.
    -- Sometimes it just hides the DebuffFrame / Icon when CC ends.
    if debuffFrame.HookScript then
        debuffFrame:HookScript("OnHide", function()
            if classIcon.ccActive then
                RestoreClassIcon(arenaIndex, classIcon, acFrame)
            end
        end)
    end

    if debuffFrame.Icon then
        if debuffFrame.Icon.HookScript then
            debuffFrame.Icon:HookScript("OnHide", function()
                if classIcon.ccActive then
                    RestoreClassIcon(arenaIndex, classIcon, acFrame)
                end
            end)
        end

        if debuffFrame.Icon.SetShown then
            hooksecurefunc(debuffFrame.Icon, "SetShown", function(_, shown)
                if shown == false and classIcon.ccActive then
                    RestoreClassIcon(arenaIndex, classIcon, acFrame)
                end
            end)
        end

        if debuffFrame.Icon.SetAlpha then
            hooksecurefunc(debuffFrame.Icon, "SetAlpha", function(_, a)
                local alpha = tonumber(a)
                if alpha and alpha <= 0.01 and classIcon.ccActive then
                    RestoreClassIcon(arenaIndex, classIcon, acFrame)
                end
            end)
        end
    end

    self.hookedFrames[arenaIndex] = true
end

function ClassIconAuras:UpdateSpiralGlowLine()
    local enabled = IsSpiralGlowLineEnabled()
    local MFM = AC.MasterFrameManager
    if not MFM or not MFM.frames then return end

    for i = 1, MAX_ARENA_ENEMIES do
        local acFrame = MFM.frames[i]
        local classIcon = acFrame and acFrame.classIcon
        local cd = classIcon and classIcon.auraCooldown
        if cd and cd.SetDrawEdge then
            cd:SetDrawEdge(enabled)
        end
    end
end

function ClassIconAuras:Initialize()
    if self.initialized then return end
    local _, instanceType = IsInInstance()
    if instanceType ~= "arena" then return end
    if IsActiveBattlefieldArena and not IsActiveBattlefieldArena() then return end

    for i = 1, MAX_ARENA_ENEMIES do
        self:HookDebuffFrame(i)
    end
    self.initialized = true
end

function ClassIconAuras:RefreshHooks()
    for i = 1, MAX_ARENA_ENEMIES do
        self:HookDebuffFrame(i)
    end
end

function ClassIconAuras:RestoreAll()
    local MFM = AC.MasterFrameManager
    if not MFM or not MFM.frames then return end

    local db = AC.DB and AC.DB.profile
    local showSpecInstead = db and db.classIcons and db.classIcons.showSpecInstead == true

    for i = 1, MAX_ARENA_ENEMIES do
        local acFrame = MFM.frames[i]
        if acFrame and acFrame.classIcon then
            local classIcon = acFrame.classIcon
            if classIcon.auraCooldown then
                classIcon.auraCooldown:Clear()
            end
            classIcon.ccActive = false
            self.ccActive[i] = false

            if showSpecInstead then
                local specID = acFrame.specID
                if (not specID or specID <= 0) and GetArenaOpponentSpec then
                    specID = GetArenaOpponentSpec(i)
                end

                if specID and specID > 0 and GetSpecializationInfoByID then
                    acFrame.specID = specID
                    local _, _, _, specIcon = GetSpecializationInfoByID(specID)
                    if specIcon and classIcon.icon and classIcon.icon.SetTexture then
                        classIcon.icon:SetTexture(specIcon)
                        if classIcon.icon.SetTexCoord then
                            classIcon.icon:SetTexCoord(0.1, 0.9, 0.1, 0.9)
                        end
                    end
                    if classIcon.overlay and classIcon.overlay.SetTexture then
                        classIcon.overlay:SetTexture("Interface\\AddOns\\ArenaCore\\Media\\Classicons\\Overlays\\orangeoverlay.tga")
                    end
                    classIcon:Show()
                else
                    classIcon:Hide()
                end

                if acFrame.specIcon then
                    acFrame.specIcon:Hide()
                end
            else
                local storedClass = acFrame.class
                if storedClass and classIcon.UpdateClassIcon then
                    classIcon.UpdateClassIcon(storedClass)
                end
            end
        end
    end
end

-- EVENTS

local eventFrame = CreateFrame("Frame")
eventFrame:RegisterEvent("PLAYER_ENTERING_WORLD")
eventFrame:RegisterEvent("ARENA_PREP_OPPONENT_SPECIALIZATIONS")
eventFrame:RegisterEvent("ARENA_OPPONENT_UPDATE")
eventFrame:RegisterEvent("GROUP_ROSTER_UPDATE")

eventFrame:SetScript("OnEvent", function(self, event, ...)
    local _, instanceType = IsInInstance()

    if event == "PLAYER_ENTERING_WORLD" then
        if instanceType == "arena" then
            C_Timer.After(0.5, function()
                if IsActiveBattlefieldArena and IsActiveBattlefieldArena() then
                    ClassIconAuras:RefreshHooks()
                end
            end)
        else
            ClassIconAuras:RestoreAll()
        end
    elseif event == "ARENA_PREP_OPPONENT_SPECIALIZATIONS" then
        ClassIconAuras:RestoreAll()
        C_Timer.After(0.1, function()
            if IsActiveBattlefieldArena and IsActiveBattlefieldArena() then
                ClassIconAuras:RefreshHooks()
            end
        end)
    elseif event == "GROUP_ROSTER_UPDATE" then
        if instanceType == "arena" then
            ClassIconAuras:RestoreAll()
        end
    elseif event == "ARENA_OPPONENT_UPDATE" then
        C_Timer.After(0.1, function()
            if IsActiveBattlefieldArena and IsActiveBattlefieldArena() then
                ClassIconAuras:RefreshHooks()
            end
        end)
    end
end)

C_Timer.After(0.5, function()
    if AC.Midnight and AC.Midnight.isMidnight then
        local _, instanceType = IsInInstance()
        if instanceType == "arena" and (not IsActiveBattlefieldArena or IsActiveBattlefieldArena()) then
            ClassIconAuras:Initialize()
        end
    end
end)
