local GAME_SPECS_OPCODE = 202

local upgradesById = {}

local function onGameSpecs(_, _, buffer)
    local ok, data = pcall(function() return json.decode(buffer) end)
    if not ok or type(data) ~= 'table' then
        return
    end

    local up = data.upgrades
    local mods = up and up.modifiers
    if type(mods) ~= 'table' then
        return
    end

    upgradesById = {}
    for _, m in ipairs(mods) do
        local id = tonumber(m.id)
        if id and id >= 1 and id <= 255 then
            upgradesById[id] = {
                name   = m.name or ('mod_' .. id),
                format = m.format or '+%d',
                tiers  = m.tiers or {},
            }
        end
    end

    if _G.gameSpecs then
        _G.gameSpecs.upgradesById = upgradesById
    end
end

local function getUpgrade(id)
    return upgradesById[id]
end

local function tierFor(id, level)
    local spec = upgradesById[id]
    if not spec or type(spec.tiers) ~= 'table' then
        return 0
    end
    local lvl = tonumber(level or 0) or 0
    if lvl <= 0 then
        return 0
    end
    for i = 1, #spec.tiers do
        local hi = tonumber(spec.tiers[i] or 0) or 0
        if lvl <= hi then
            return i
        end
    end
    return #spec.tiers
end

function init()
    ProtocolGame.registerExtendedOpcode(GAME_SPECS_OPCODE, onGameSpecs)
    _G.gameSpecs = {
        upgradesById = upgradesById,
        getUpgrade = getUpgrade,
        tierFor = tierFor,
    }
end

function terminate()
    ProtocolGame.unregisterExtendedOpcode(GAME_SPECS_OPCODE, onGameSpecs)
    upgradesById = {}
    _G.gameSpecs = nil
end
