-------------------------------------------------------------------------------
-- RealNibba's Raid Tools - Parser.lua  v3.10
-- CHAT_MSG_RAID_WARNING + CHAT_MSG_ADDON  (3.3.5a, arg1/arg2/arg3 globals)
--
-- Spam protection design:
-- All clients see the same /rw at roughly the same time.
-- Each client:
--   1. Rolls a random fireAt time (now + 0.3 to 0.6 seconds).
--   2. Immediately broadcasts "CLAIM:<itemkey>:<fireAt>" to the raid.
--   3. Listens for CLAIM messages from other clients.
--      If another client's fireAt is LOWER than ours, we cancel ourselves.
--   4. When our timer fires, if not cancelled, we announce.
--
-- 3.3.5a notes:
--   RegisterAddonMessagePrefix does not exist in Wrath - do not call it.
--   CHAT_MSG_ADDON does not echo back to the sender.
--   arg1/arg2/arg3/arg4 are globals in OnEvent (no self/event params).
-------------------------------------------------------------------------------

local ADDON_PREFIX = "BISRAID"
-- RegisterAddonMessagePrefix does not exist in WoW 3.3.5a - intentionally omitted.

local parserFrame = CreateFrame("Frame", "BiSRaid_ParserFrame", UIParent)
parserFrame:RegisterEvent("CHAT_MSG_RAID_WARNING")
parserFrame:RegisterEvent("CHAT_MSG_ADDON")

local cooldowns = {}
local pending   = {}

local pendingFrame = CreateFrame("Frame", "BiSRaid_PendingFrame", UIParent)
pendingFrame:SetScript("OnUpdate", function()
    local now = GetTime()
    for key, p in pairs(pending) do
        if now >= p.fireAt then
            pending[key] = nil
            if not p.cancelled then
                if p.bisStr ~= "" then
                    BiSRaid_AddQueue("[" .. p.bracketName .. "] BiS: " .. p.bisStr)
                end
                if p.altStr ~= "" then
                    BiSRaid_AddQueue("[" .. p.bracketName .. "] Alt: " .. p.altStr)
                end
            end
        end
    end
end)

local function GetOrBuildText(entry, field, tableField)
    -- cached string
    if type(entry[field]) == "string" and entry[field] ~= "" and entry[field] ~= "(None)" then
        return entry[field]
    end
    -- build from sequence table using explicit counter (# unreliable in WoW Lua 5.1)
    if type(entry[tableField]) == "table" then
        local parts, n = {}, 0
        for i = 1, 200 do
            if entry[tableField][i] then
                n = n + 1
                parts[n] = entry[tableField][i]
            else
                break
            end
        end
        if n > 0 then
            local built = table.concat(parts, " / ")
            entry[field] = built
            return built
        end
    end
    -- legacy: alt stored as plain string (original BiSRaid format)
    if tableField == "alt" and type(entry.alt) == "string" and entry.alt ~= "" then
        return entry.alt
    end
    return ""
end

parserFrame:SetScript("OnEvent", function()
    ---------------------------------------------------------------------------
    -- Addon messages from other RNTools clients
    ---------------------------------------------------------------------------
    if event == "CHAT_MSG_ADDON" then
        if arg1 ~= ADDON_PREFIX then return end
        local itemKey, theirFireAt = string.match(arg2, "^CLAIM:([^:]+):([%d%.]+)$")
        if itemKey and theirFireAt then
            theirFireAt = tonumber(theirFireAt)
            local p = pending[itemKey]
            if p and not p.cancelled then
                if theirFireAt < p.fireAt then
                    p.cancelled = true
                end
            end
        end
        return
    end

    ---------------------------------------------------------------------------
    -- Raid warning - main detection path
    ---------------------------------------------------------------------------
    if event ~= "CHAT_MSG_RAID_WARNING" then return end

    if not BiSRaidConfig or BiSRaidConfig.enabled == false then return end

    local msg = arg1
    if not msg or msg == "" then return end

    for bracketName in string.gmatch(msg, "%[(.-)%]") do
        if bracketName ~= "" then
            -- Our DB keys are lowercase
            local loName = string.lower(bracketName)
            local data   = BiSRaidDB and BiSRaidDB.items and BiSRaidDB.items[loName]

            if data then
                local now = GetTime()
                if not cooldowns[loName] or (now - cooldowns[loName]) >= 10 then
                    cooldowns[loName] = now

                    local bisStr = GetOrBuildText(data, "bis_text", "bis")
                    local altStr = GetOrBuildText(data, "alt_text", "alt")

                    if bisStr ~= "" or altStr ~= "" then
                        local displayName = (data.display and data.display ~= "") and data.display or bracketName

                        if GetNumRaidMembers() > 0 then
                            local jitter = 0.3 + math.random(4) * 0.1   -- 0.3..0.6 s
                            local fireAt = now + jitter

                            pending[loName] = {
                                bisStr      = bisStr,
                                altStr      = altStr,
                                bracketName = displayName,
                                fireAt      = fireAt,
                                cancelled   = false,
                            }

                            SendAddonMessage(ADDON_PREFIX,
                                "CLAIM:" .. loName .. ":" .. fireAt,
                                "RAID")
                        else
                            -- Solo / test mode: announce immediately
                            if bisStr ~= "" then
                                BiSRaid_AddQueue("[" .. displayName .. "] BiS: " .. bisStr)
                            end
                            if altStr ~= "" then
                                BiSRaid_AddQueue("[" .. displayName .. "] Alt: " .. altStr)
                            end
                        end
                    end
                end
            end
        end
    end
end)
