
MudSystemSettingsSyncEvent = MudSystemSettingsSyncEvent or {}
local MudSystemSettingsSyncEvent_mt = Class(MudSystemSettingsSyncEvent, Event)

local EVENT_NAME = "MudSystemPhysics.MudSystemSettingsSyncEvent"

if MudSystemSettingsSyncEvent.eventId == nil then
    InitEventClass(MudSystemSettingsSyncEvent, EVENT_NAME)
end

function MudSystemSettingsSyncEvent.emptyNew()
    return Event.new(MudSystemSettingsSyncEvent_mt)
end

function MudSystemSettingsSyncEvent.new(isRequest, snapshot)
    local self = MudSystemSettingsSyncEvent.emptyNew()
    self.isRequest = isRequest == true
    self.snapshot = snapshot
    return self
end

local function ensureStreamId(streamId, connection)
    if type(streamId) ~= "number" and type(connection) == "number" then
        return connection, streamId
    end
    return streamId, connection
end

function MudSystemSettingsSyncEvent:writeStream(streamId, connection)
    streamId, connection = ensureStreamId(streamId, connection)
    if type(streamId) ~= "number" then
        return
    end

    streamWriteBool(streamId, self.isRequest)

    if not self.isRequest then
        local settings = _G["MudSystemSettings"]
        local items = settings and settings.items

        if items ~= nil then
            for i, item in ipairs(items) do
                local v = self.snapshot and self.snapshot[i]
                if item.type == "bool" then
                    streamWriteBool(streamId, v == true)
                else
                    streamWriteFloat32(streamId, tonumber(v) or 0)
                end
            end
        end
    end
end

function MudSystemSettingsSyncEvent:readStream(streamId, connection)
    streamId, connection = ensureStreamId(streamId, connection)
    if type(streamId) ~= "number" then
        return
    end

    self.isRequest = streamReadBool(streamId)

    local settings = _G["MudSystemSettings"]

    if self.isRequest then
        if g_server ~= nil and settings ~= nil and settings.collectSnapshot ~= nil then
            local snap = settings:collectSnapshot()
            if connection ~= nil and connection.sendEvent ~= nil then
                connection:sendEvent(MudSystemSettingsSyncEvent.new(false, snap))
            end
        end
        return
    end

    if settings == nil or settings.items == nil then
        return
    end

    local snap = {}
    for i, item in ipairs(settings.items) do
        if item.type == "bool" then
            snap[i] = streamReadBool(streamId)
        else
            snap[i] = streamReadFloat32(streamId)
        end
    end

    if g_server ~= nil then
        if settings.applySnapshot ~= nil then
            settings:applySnapshot(snap, true)
        end
        g_server:broadcastEvent(MudSystemSettingsSyncEvent.new(false, snap), false)
    else
        if settings.applySnapshot ~= nil then
            settings:applySnapshot(snap, false)
        end
        if settings.writeSettings ~= nil then
            settings:writeSettings()
        end
    end
end

function MudSystemSettingsSyncEvent.sendRequest()
    if g_client ~= nil and g_client.getServerConnection ~= nil then
        g_client:getServerConnection():sendEvent(MudSystemSettingsSyncEvent.new(true))
    end
end

function MudSystemSettingsSyncEvent.sendSnapshot(snapshot)
    if snapshot == nil then
        return
    end

    if g_server ~= nil then
        g_server:broadcastEvent(MudSystemSettingsSyncEvent.new(false, snapshot), false)
    elseif g_client ~= nil and g_client.getServerConnection ~= nil then
        local isAdmin = (g_currentMission ~= nil) and (g_currentMission.isMasterUser == true)
        if not isAdmin then
            return
        end
        g_client:getServerConnection():sendEvent(MudSystemSettingsSyncEvent.new(false, snapshot))
    end
end
