-- ============================================================
-- FILE: Messenger_DMAlert.lua
-- PURPOSE: Stand-alone visual alert for unread direct messages.
--   Keeps Messenger.lua's chunk free of the strip/halo construction
--   code (~50 textures total) which was pushing it close to Lua's
--   200-local-per-function compile limit.
-- HOW IT WORKS:
--   On addon load, attaches two cyan pulse effects:
--     1. A 56-px-wide soft fade on the LEFT EDGE of the expanded
--        Messenger window (built from 56 single-pixel strips with
--        a gamma-curved alpha falloff).
--     2. A 36-px concentric-square halo around the COLLAPSED
--        bubble (18 stacked layers with explicit sublevels for
--        stable draw order).
--   Both share the same RealID-cyan color (BATTLENET_FONT_COLOR)
--   and the same 3-second IN_OUT pulse.
--   Exposes _G.MidnightUI_UpdateDMUnreadAlert() — Messenger.lua
--   calls this from UpdateTabLayout whenever badge counts refresh.
-- DEPENDS ON:
--   _G.MyMessengerFrame                — created by Messenger.lua
--   _G.MidnightMessengerCollapsedBubble — created by Messenger.lua
--   MessengerDB.History["Direct"].unread — the unread-DM source
-- EXPORTS:
--   _G.MidnightUI_UpdateDMUnreadAlert   — toggle callback
-- OWNED SAVEDVARIABLES: none
-- EVENTS REGISTERED: none (driven by Messenger's UpdateTabLayout)
-- FRAMES CREATED:
--   one container Frame on the Messenger window (the strip group)
--   one container Frame on the collapsed bubble  (the halo group)
-- GOTCHAS:
--   * Must load AFTER Messenger.lua in the .toc — the two parent
--     frames have to exist before this file's setup runs.
--   * The bubble halo intentionally uses constant per-layer alpha
--     (0.035, well above the renderer's culling threshold) to
--     avoid the flicker an earlier gamma-curved version produced.
-- ============================================================

local W8 = "Interface\\Buttons\\WHITE8X8"

-- RealID cyan, with a hardcoded fallback if BATTLENET_FONT_COLOR
-- isn't defined yet at load time (defensive).
local function CyanColor()
    local r, g, b = 0.32, 0.77, 1.00
    if _G.BATTLENET_FONT_COLOR then
        r = _G.BATTLENET_FONT_COLOR.r or r
        g = _G.BATTLENET_FONT_COLOR.g or g
        b = _G.BATTLENET_FONT_COLOR.b or b
    end
    return r, g, b
end

-- ── Expanded Messenger window: left-edge soft fade ─────────
local function BuildWindowPulse(messenger)
    if not messenger then return end
    local cR, cG, cB = CyanColor()

    local PULSE_W = 56
    local pulse = CreateFrame("Frame", nil, messenger)
    pulse:SetWidth(PULSE_W)
    pulse:SetPoint("TOPLEFT",    messenger, "TOPLEFT",    0, 0)
    pulse:SetPoint("BOTTOMLEFT", messenger, "BOTTOMLEFT", 0, 0)
    pulse:SetFrameLevel(messenger:GetFrameLevel() + 5)
    pulse:SetAlpha(0)
    pulse:Hide()

    -- Single-pixel strips, gamma-curved alpha for a smooth fade
    -- from opaque cyan at the left to invisible at the right.
    for i = 1, PULSE_W do
        local t = (PULSE_W - i) / (PULSE_W - 1)   -- 1.0 → 0.0
        local a = t ^ 2.4
        local strip = pulse:CreateTexture(nil, "OVERLAY", nil, 7)
        strip:SetWidth(1)
        strip:SetPoint("TOPLEFT",    pulse, "TOPLEFT",    i - 1, 0)
        strip:SetPoint("BOTTOMLEFT", pulse, "BOTTOMLEFT", i - 1, 0)
        strip:SetColorTexture(cR, cG, cB, a)
        strip:SetBlendMode("ADD")
    end

    local ag = pulse:CreateAnimationGroup()
    ag:SetLooping("REPEAT")
    local up   = ag:CreateAnimation("Alpha")
    up:SetFromAlpha(0.30); up:SetToAlpha(0.70)
    up:SetDuration(1.5);   up:SetSmoothing("IN_OUT"); up:SetOrder(1)
    local down = ag:CreateAnimation("Alpha")
    down:SetFromAlpha(0.70); down:SetToAlpha(0.30)
    down:SetDuration(1.5);   down:SetSmoothing("IN_OUT"); down:SetOrder(2)

    messenger._dmPulse     = pulse
    messenger._dmPulseAnim = ag
end

-- ── Collapsed bubble: concentric-square halo ───────────────
local function BuildBubbleHalo(bubble)
    if not bubble then return end
    local cR, cG, cB = CyanColor()
    local size = bubble:GetWidth() or 46

    local halo = CreateFrame("Frame", nil, bubble)
    halo:SetPoint("CENTER", bubble, "CENTER", 0, 0)
    halo:SetSize(size, size)
    halo:SetFrameStrata(bubble:GetFrameStrata())
    halo:SetFrameLevel(math.max(0, bubble:GetFrameLevel() - 1))
    halo:SetAlpha(0)
    halo:Hide()

    -- 16 concentric square layers, 2px step per layer.
    -- Explicit sublevels in WoW's legal [-8, 7] range lock the
    -- draw order so the renderer can't reshuffle layers per frame.
    -- Per-layer alpha follows a gamma curve (^1.7) — the innermost
    -- layer carries the bulk of the brightness, the outermost
    -- fades to 0. Combined with the locked sublevels, the very
    -- faint outer layers don't flicker (which earlier same-layer
    -- versions did) and the perimeter dissolves into the backdrop
    -- with no visible edge.
    local LAYER_COUNT = 16
    local STEP_PX     = 2
    local PEAK_A      = 0.07
    for i = 1, LAYER_COUNT do
        local t = (i - 1) / (LAYER_COUNT - 1)   -- 0 = innermost, 1 = outermost
        local a = (1 - t) ^ 1.7 * PEAK_A
        local pad = i * STEP_PX
        local sublevel = 8 - i   -- i=1 → +7 (innermost); i=16 → -8 (outermost)
        local layer = halo:CreateTexture(nil, "BACKGROUND", nil, sublevel)
        layer:SetPoint("TOPLEFT",     halo, "TOPLEFT",     -pad,  pad)
        layer:SetPoint("BOTTOMRIGHT", halo, "BOTTOMRIGHT",  pad, -pad)
        layer:SetColorTexture(cR, cG, cB, a)
        layer:SetBlendMode("ADD")
    end

    local ag = halo:CreateAnimationGroup()
    ag:SetLooping("REPEAT")
    local up   = ag:CreateAnimation("Alpha")
    up:SetFromAlpha(0.45); up:SetToAlpha(0.80)
    up:SetDuration(1.5);   up:SetSmoothing("IN_OUT"); up:SetOrder(1)
    local down = ag:CreateAnimation("Alpha")
    down:SetFromAlpha(0.80); down:SetToAlpha(0.45)
    down:SetDuration(1.5);   down:SetSmoothing("IN_OUT"); down:SetOrder(2)

    bubble._dmHalo     = halo
    bubble._dmHaloAnim = ag
end

-- ── Build effects + expose the toggle callback ─────────────
BuildWindowPulse(_G.MyMessengerFrame)
BuildBubbleHalo(_G.MidnightMessengerCollapsedBubble)

_G.MidnightUI_UpdateDMUnreadAlert = function()
    local count = 0
    if MessengerDB and MessengerDB.History and MessengerDB.History["Direct"] then
        count = MessengerDB.History["Direct"].unread or 0
    end

    local m = _G.MyMessengerFrame
    if m and m._dmPulse and m._dmPulseAnim then
        if count > 0 then
            m._dmPulse:Show()
            if not m._dmPulseAnim:IsPlaying() then m._dmPulseAnim:Play() end
        else
            m._dmPulseAnim:Stop()
            m._dmPulse:SetAlpha(0)
            m._dmPulse:Hide()
        end
    end

    local b = _G.MidnightMessengerCollapsedBubble
    if b and b._dmHalo and b._dmHaloAnim then
        if count > 0 then
            b._dmHalo:Show()
            if not b._dmHaloAnim:IsPlaying() then b._dmHaloAnim:Play() end
        else
            b._dmHaloAnim:Stop()
            b._dmHalo:SetAlpha(0)
            b._dmHalo:Hide()
        end
    end
end
