-- 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 "?"

-- Short chat prefix on every line. The running version is shown ONCE on login (banner below),
-- not repeated on every message.
WB.TAG = "|cffff8800[WarBoard]|r"

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

-- One-time version banner on login — the only line that prints the version number.
do
    local f = CreateFrame("Frame")
    f:RegisterEvent("PLAYER_LOGIN")
    f:SetScript("OnEvent", function(self)
        print(("|cffff8800[WarBoard v%s]|r loaded \226\128\148 |cffffd100/wb|r to open.")
            :format(tostring(WB.VERSION or "?")))
        self:UnregisterEvent("PLAYER_LOGIN")
    end)
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 = 9   -- v9: "breaking_badlands_race" reward set to 150g/75wc (rewards now enabled)
                  -- v8: "breaking_badlands_race" elite objective added
                  -- v7: supply_run earns the active-warfront bonus (boosted reward is now legal)
                  -- v6: "supply_run" activity type (Supply Run delivery + stolen-cargo turn-in)
                  -- v5: Val & Naigtal weekly-flip player fronts ("Cold Blooded" / "Spore Losers")
                  -- v4: bounty gold reward nerfed to half the post cost
                  -- v3: Midnight player fronts — Eversong Woods, Zul'Aman, Harandar (released in 1.1.0)

-- Canonical Supply Run reward (per delivered shipment). BOTH a completed daily Supply Run
-- and a turned-in STOLEN shipment pay this exact amount — the Verifier validates the
-- "supply_run" activity type against these fixed values, so they must stay in lockstep with
-- WB.RULESVER (change the numbers → bump RULESVER). Referenced by the run/cargo layers and
-- the Verifier alike so there is a single source of truth.
WB.SUPPLY_REWARD = { gold = 300, warCredit = 150 }

-- 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("|K.-|k", "")                               -- kstring (a client-LOCAL string index — a
                                                           -- crafted one resolves to a hidden string on
                                                           -- the VIEWER's machine, so never honour it)
    s = s:gsub("|n", " ")                                  -- embedded newline
    s = s:gsub("|", "")                                    -- any stray escape pipe (catch-all backstop)
    maxLen = maxLen or 80
    if #s > maxLen then s = s:sub(1, maxLen) .. "\226\128\166" end   -- … ellipsis
    return s
end
