-- WarBoard_Core.lua
-- Version + the shared chat prefix. Loaded before everything else so WB.TAG / WB.VERSION
-- exist for any chat line the addon prints.

local addonName, WB = ...

local function Meta(field)
    local getter = (C_AddOns and C_AddOns.GetAddOnMetadata) or GetAddOnMetadata
    return getter and getter(addonName, field) or nil
end

WB.VERSION = Meta("Version") or "?"

-- Every user-facing chat line carries the running version: "[WarBoard (Ver X)] ...".
WB.TAG = "|cffff8800[WarBoard (Ver " .. WB.VERSION .. ")]|r"

function WB.Print(msg) print(WB.TAG .. " " .. tostring(msg)) end

-- Compare dotted numeric versions, ignoring any suffix like "-alpha". Returns >0 if a>b,
-- 0 if equal, <0 if a<b. ("1.2" vs "1.2.1" → -1; "1.3-alpha" vs "1.2" → +1.)
function WB.CompareVersions(a, b)
    local function parts(v)
        local maj, min, pat = tostring(v or ""):match("(%d+)%.?(%d*)%.?(%d*)")
        return tonumber(maj) or 0, tonumber(min) or 0, tonumber(pat) or 0
    end
    local a1, a2, a3 = parts(a)
    local b1, b2, b3 = parts(b)
    if a1 ~= b1 then return a1 - b1 end
    if a2 ~= b2 then return a2 - b2 end
    return a3 - b3
end

-- ── Instanced-content gate ─────────────────────────────────────────────────────
-- War Board is a WORLD PvP addon and stands down completely inside any instance
-- (battleground, arena, dungeon, raid, scenario): no kill tracking, no earning, no
-- objective progress, and no addon communication. In instanced PvP and instanced PvE
-- the game also hands addons "secret" values for combat data (GUIDs, etc.) that can't
-- be read or compared without tainting us — so the kill handlers bail the moment they
-- see one. These two helpers are the single gate used across the addon.

-- True inside ANY instance. Second return is the instanceType ("pvp"/"arena"/"party"/
-- "raid"/"scenario"/"none") for callers that want to tell instanced PvP from PvE.
function WB.InInstance()
    local inInstance, instanceType = IsInInstance()
    if inInstance and instanceType and instanceType ~= "none" then
        return true, instanceType
    end
    return false, instanceType
end

-- True when the restricted (instanced) game environment has marked a value secret —
-- i.e. a combat GUID/field the addon isn't allowed to read. Reading or comparing it
-- would taint us, so callers must bail when this returns true. Safe on nil.
function WB.IsSecret(v)
    if v == nil or issecretvalue == nil then return false end
    return issecretvalue(v) and true or false
end

-- ── Rules version (forward/backward compatibility) ──────────────────────────────
-- The version of the addon's *validation rules*: the objective catalog, the activity
-- types, and the bounty rank tiers. Bump this ONLY when that catalog changes (a new
-- objective, atype, or rank) — NOT for cosmetic/UI releases. Every record stamps the
-- RULESVER it was created under (Ledger MakeRecord → rec.rv). When we meet a record we
-- can't fully judge (an objId/atype/rank we don't have), we abstain instead of convicting
-- ONLY if it claims a newer RULESVER than ours — i.e. we might simply be out of date.
-- If it claims our version or older, we should have known it, so it's fabricated.
--
-- ►► When you add a new objective / atype / rank, increment this by 1. ◄◄
WB.RULESVER = 4   -- v4: bounty gold reward nerfed to half the post cost
                  -- v3: Midnight player fronts — Eversong Woods, Zul'Aman, Harandar (released in 1.1.0)

-- Make an untrusted display string — e.g. a title carried on a synced record that
-- originated on another player's client — safe to print. Strips UI escape sequences
-- (colour codes, hyperlinks, textures) so a crafted record can't inject markup, and
-- caps the length. Display-only; never used for validation.
function WB.SanitizeDisplay(s, maxLen)
    if type(s) ~= "string" then return s end
    s = s:gsub("|c%x%x%x%x%x%x%x%x", ""):gsub("|r", "")   -- colour open/close
    s = s:gsub("|H.-|h(.-)|h", "%1")                       -- hyperlink → keep the text
    s = s:gsub("|T.-|t", "")                               -- inline texture
    s = s:gsub("|A.-|a", "")                               -- inline atlas
    s = s:gsub("|n", " ")                                  -- embedded newline
    s = s:gsub("|", "")                                    -- any stray escape pipe
    maxLen = maxLen or 80
    if #s > maxLen then s = s:sub(1, maxLen) .. "\226\128\166" end   -- … ellipsis
    return s
end
