cRegistry = {}

-- AddInt|Float, SubInt|Float, MulInt|Float, DivInt|Float, ModInt|Float, PowInt|Float
local function regOper(reg, value_type, value, oper)
    local oldVal = _G["Get" .. value_type](reg)
    local newVal
    if HasKey(reg) and oldVal ~= "" then
        if type(oldVal) == 'string' then
            oldVal = [==["]==] .. oldVal .. [==["]==]
            value = [==["]==] .. value .. [==["]==]
            newVal = loadstring('return ' .. oldVal .. ' ' .. oper .. ' ' .. value)()
        else
            newVal = loadstring('return ' .. oldVal .. ' ' .. oper .. ' ' .. value)()
        end
    else
        newVal = value
    end
    _G["Set" .. value_type](reg, newVal)
    return newVal
end

local typ = {'Int', 'Float'}
for i = 1, #typ do
    for k, v in pairs({
        ['+'] = 'Add',
        ['-'] = 'Sub',
        ['*'] = 'Mul',
        ['/'] = 'Div',
        ['%'] = 'Mod',
        ['^'] = 'Pow',
    }) do
        cRegistry[v .. typ[i]] = function(_, reg, val) return regOper(reg, typ[i], val, k) end
    end
end
function cRegistry:AppendString(reg, val, sep)
    local oper = [==[.."]==] .. (sep or '') .. [==["..]==]
    return regOper(reg, 'String', val, oper)
end

function cRegistry:GetVehiclePlayer(vehicle_handle)
    -- if GetEntityType(vehicle_handle) ~= "vehicle" then return end
    if type(vehicle_handle) ~= "number" then return end
    local reg = "level.players"
    local keys = ListKeys(reg)
    for i = 1, #keys do
        local handle = GetInt(reg .. '.' .. i)
        if math.abs(handle) == vehicle_handle then
            return i, handle < 0
        end
    end
end

local cached_transforms
function cRegistry:GetTransformPlayer(id, including_rotation)
    local pos = GetColor("transform." .. id .. ".pos")
    local rot = including_rotation and GetColor("transform." .. id .. ".rot") or nil
    if not cached_transforms then
        local tr = Transform(pos, rot)
        cached_transforms = { [id] = tr }
        return tr
    else
        local cached = cached_transforms[id]
        if cached then
            cached.pos = pos
            cached.rot = rot
            return cached
        else
            local tr = Transform(pos, rot)
            cached_transforms[id] = tr
            return tr
        end
    end
end

function cRegistry:GetModFolderPath()
    return GetString("game.levelpath"):match"^(.*)[/].*$"
end

function cRegistry:FixOldSaves()
    local path = "savegame.mod."

    -- Message changes
    if HasKey(path .. "messageque") then
        local i = 0
        local msgs = {}
        local parts = {}
        SetString(path .. "messageque", GetString(path .. "messageque"):gsub("(,?)([^,]+)", function(comma,s)
            i = i + 1
            msgs[#msgs+1] = s
            if s == "championship_9" then
                return ""
            elseif s:find"championship_9_p" then
                parts[i] = s
            end
            return comma .. s
        end))
        local indices = {}
        for k, v in pairs(parts) do
            indices[#indices+1] = {k, v}
        end
        table.sort(indices, function(a, b)
            if a[2]<b[2] then
                a[1],b[1] = b[1],a[1]
                return true
            end
            return false
        end)
        for j = 1, #indices do
            local k, v = unpack(indices[j])
            msgs[k] = v
        end
        SetString(path .. "messageque", table.concat(msgs, ","))
    end

    if HasKey(path .. "message.championship_9_p1") then
        if not GetBool(path .. "message.championship_9_p1")
        or not GetBool(path .. "message.championship_9_p1.read")
        or not GetBool(path .. "message.championship_9_p2")
        or not GetBool(path .. "message.championship_9_p2.read")
        then
            ClearKey(path .. "message.championship_9_p1")
            ClearKey(path .. "message.championship_9_p2")
            SetString(path .. "messageque", GetString(path .. "messageque"):gsub("(,?)championship_9_p%d(,?)",
                function(s1,s2) return s1~=''and s2~=''and','or"" end
            ))
        end
    end
    ClearKey("savegame.mod.prepare-data")
end
