---@diagnostic disable: undefined-field, undefined-global
---@type string
local AddonName = ...
---@class Private
local Private = select(2, ...)
local wt = Private.Ace
---@class WTAPI
local WTAPI = WTAPI

local Media = LibStub("LibSharedMedia-3.0")

local drink_frame = nil
local drink_frame_text = nil
local drink_frame_hue = 0
local drink_frame_time = 0

local police_frame = nil
local police_frame_text = nil
local police_frame_time = 0

local colorTicker, bounceTicker
local police_frame_colorTicker, police_frame_bounceTicker

local timers = {}
local party_sounds = {
    ["WT Dragonball"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\dragonball.ogg",
    ["WT Wein"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\griechischer_wein.ogg",
    ["WT Links Rechts"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\links_rechts.ogg",
    ["WT Ouzo"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\ouzo.ogg",
    ["WT Pedro"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\pedro.ogg",
    ["WT Pyro"] = "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\pyrotechnik.ogg",
}

for k, v in pairs(party_sounds) do
    Media:Register("sound", k, v)
end

Media:Register("sound", "WT Police", "Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\police.ogg")

function wt:PartyMode_EncounterStart()
    print("|cff99ff00Wild Things:|r ", "Party Mode initiated!")
    wt:PartyTimer()
end

function wt:PartyMode_EncounterEnd()
    for _, timer in pairs(timers) do
        if timer and not timer:IsCancelled() then
            timer:Cancel()
        end
    end
    -- wipe, not `timer = nil` inside the loop above: that only reassigned the loop variable,
    -- so `timers` was append-only and every encounter iterated over more dead handles.
    wipe(timers)

    wt:StopParty()
    -- StopPolice too: the loop above just cancelled the timer that would have called it, so
    -- a police overlay that was still up at encounter end used to stay on screen until the
    -- next activation.
    wt:StopPolice()
end

function wt:PartyTimer()
    table.insert(
        timers,
        C_Timer.NewTimer(math.random(20, 120),
            function()
                local keys = {}
                for key in pairs(party_sounds) do
                    table.insert(keys, key)
                end
                local sound_name = keys[math.random(#keys)]

                local sound = Media:Fetch('sound', sound_name)

                local duration = 3

                Private:Broadcast("PARTY", "RAID", sound, duration)

                wt:PartyTimer()
            end
        )
    )
end

function wt:ActivateParty(sound, duration)
    if sound then
        PlaySoundFile(sound, "Master")
    end

    if not drink_frame and not drink_frame_text then
        drink_frame = CreateFrame("Frame")
        drink_frame:SetWidth(100)
        drink_frame:SetHeight(100)
        drink_frame:SetPoint("CENTER", UIParent, "CENTER")
        drink_frame:SetFrameStrata("MEDIUM")
        drink_frame_text = drink_frame:CreateFontString()
        drink_frame_text:SetPoint("CENTER", drink_frame, "CENTER", 0, 200)
        drink_frame_text:SetFont("Interface\\AddOns\\WildThings\\Media\\Fonts\\Expressway.ttf", 40, "OUTLINE")
        drink_frame_text:SetText(Private.gsubIcon(236827, 16, 16) .. "Drink!")
    else
        drink_frame_text:SetShown(true)
    end

    -- Starte Farbwechsel-Effekt
    if not colorTicker then
        colorTicker = C_Timer.NewTicker(0.05, function()
            drink_frame_hue = (drink_frame_hue + 10) % 360
            local r, g, b = Private:HSVtoRGB(drink_frame_hue, 1, 1)
            drink_frame_text:SetTextColor(r, g, b, 1)
        end)
    end

    -- Starte sanftes Hüpfen (Ease In-Out)
    if not bounceTicker then
        bounceTicker = C_Timer.NewTicker(0.01, function()
            drink_frame_time = drink_frame_time + 0.08  -- Geschwindigkeit der Welle
            local yOffset = 190 + (math.sin(drink_frame_time) * 22)  -- Sanft zwischen 175-205px bewegen
            drink_frame_text:SetPoint("CENTER", drink_frame, "CENTER", 0, yOffset)
        end)
    end

    -- Timer zum Stoppen
    table.insert(
        timers,
        C_Timer.NewTimer(tonumber(duration), function()
            wt:StopParty()
        end)
    )
end

function wt:StopParty()
    -- drink_frame_text only exists once ActivateParty has run, which needs an incoming
    -- PARTY comm delivered over WT_MSG -- and that fires on a math.random(20, 120)s timer.
    -- ENCOUNTER_END calls through to here regardless (Core.lua:94), so as raid lead every
    -- pull that ended before the first party sound used to error on a nil frame.
    if drink_frame_text then
        drink_frame_text:SetShown(false)
    end
    if colorTicker then
        colorTicker:Cancel()
        colorTicker = nil
    end
    if bounceTicker then
        bounceTicker:Cancel()
        bounceTicker = nil
    end
end

function wt:ActivatePartyPolice(name, duration)
    PlaySoundFile("Interface\\AddOns\\WildThings\\Media\\PartyMode\\Sounds\\police.ogg", "Master")

    if not police_frame and not police_frame_text then
        police_frame = CreateFrame("Frame")
        police_frame:SetWidth(100)
        police_frame:SetHeight(100)
        police_frame:SetPoint("CENTER", UIParent, "CENTER")
        police_frame:SetFrameStrata("MEDIUM")
        police_frame_text = police_frame:CreateFontString()
        police_frame_text:SetPoint("CENTER", police_frame, "CENTER", 0, 200)
        police_frame_text:SetFont("Interface\\AddOns\\WildThings\\Media\\Fonts\\Expressway.ttf", 20, "OUTLINE")
        police_frame_text:SetText(Private.gsubIcon(231193, 16, 16) .. "|cffffff00" .. name .. "|r wurde erwischt! Trinken! " .. Private.gsubIcon(231193, 16, 16))
    else
        police_frame_text:SetShown(true)
    end

    -- Starte Farbwechsel-Effekt
    if not police_frame_colorTicker then
        local isRed = true  -- Zustand für den Farbwechsel
        police_frame_colorTicker = C_Timer.NewTicker(0.33, function()
            if isRed then
                police_frame_text:SetTextColor(1, 0, 0, 1)  -- Rot
            else
                police_frame_text:SetTextColor(0, 0, 1, 1)  -- Blau
            end
            isRed = not isRed  -- Zustand umkehren
        end)
    end

    -- Starte sanftes Hüpfen (Ease In-Out)
    if not police_frame_bounceTicker then
        police_frame_bounceTicker = C_Timer.NewTicker(0.01, function()
            police_frame_time = police_frame_time + 0.08  -- Geschwindigkeit der Welle
            local yOffset = 190 + (math.sin(police_frame_time) * 22)  -- Sanft zwischen 175-205px bewegen
            police_frame_text:SetPoint("CENTER", police_frame, "CENTER", 0, yOffset)
        end)
    end

    -- Timer zum Stoppen
    table.insert(
        timers,
        C_Timer.NewTimer(tonumber(duration), function()
            wt:StopPolice()
        end)
    )
end

function wt:StopPolice()
    -- Same guard as StopParty: now that PartyMode_EncounterEnd calls this too, it is
    -- reachable before ActivatePartyPolice has ever built the frame.
    if police_frame_text then
        police_frame_text:SetShown(false)
    end
    if police_frame_colorTicker then
        police_frame_colorTicker:Cancel()
        police_frame_colorTicker = nil
    end
    if police_frame_bounceTicker then
        police_frame_bounceTicker:Cancel()
        police_frame_bounceTicker = nil
    end
end



function wt:CheckPartyModeRequirements()
    if WildThingsSavedVars.update.party_mode then
        local index = UnitInRaid("player")
        if index then
            local rank = select(2, GetRaidRosterInfo(index))
            local raid_difficulty = GetRaidDifficultyID()
            if rank == 2 and raid_difficulty ~= 16 then
                return true
            end
        end
    end
    return false
end

function wt:CheckPartyModeReceiverRequirements()
    if WildThingsSavedVars.update.party_mode then
        local raid_difficulty = GetRaidDifficultyID()
        if raid_difficulty ~= 16 then
            return true
        end
    end
    return false
end

