RoadGarbageEvent = {}
local RoadGarbageEvent_mt = Class(RoadGarbageEvent, Event)
InitEventClass(RoadGarbageEvent, "MudSystemPhysics.RoadGarbageEvent")

RoadGarbageEvent.ACTION_ADD = 1
RoadGarbageEvent.ACTION_REMOVE = 2
RoadGarbageEvent.ACTION_CLEAR = 3
RoadGarbageEvent.ACTION_REQUEST = 4

function RoadGarbageEvent.emptyNew()
    return Event.new(RoadGarbageEvent_mt)
end

function RoadGarbageEvent.new(action, objectId, x, z, rotY, modelIndex)
    local self = RoadGarbageEvent.emptyNew()
    self.action = action or RoadGarbageEvent.ACTION_REQUEST
    self.objectId = objectId or 0
    self.x = x or 0
    self.z = z or 0
    self.rotY = rotY or 0
    self.modelIndex = modelIndex or 1
    return self
end

function RoadGarbageEvent:writeStream(streamId, connection)
    streamWriteUInt8(streamId, self.action)

    if self.action == RoadGarbageEvent.ACTION_ADD then
        streamWriteUInt16(streamId, self.objectId)
        streamWriteFloat32(streamId, self.x)
        streamWriteFloat32(streamId, self.z)
        streamWriteFloat32(streamId, self.rotY)
        streamWriteUInt8(streamId, self.modelIndex)
    elseif self.action == RoadGarbageEvent.ACTION_REMOVE then
        streamWriteUInt16(streamId, self.objectId)
    end
end

function RoadGarbageEvent:readStream(streamId, connection)
    self.action = streamReadUInt8(streamId)

    if self.action == RoadGarbageEvent.ACTION_ADD then
        self.objectId = streamReadUInt16(streamId)
        self.x = streamReadFloat32(streamId)
        self.z = streamReadFloat32(streamId)
        self.rotY = streamReadFloat32(streamId)
        self.modelIndex = streamReadUInt8(streamId)
    elseif self.action == RoadGarbageEvent.ACTION_REMOVE then
        self.objectId = streamReadUInt16(streamId)
    end

    self:run(connection)
end

function RoadGarbageEvent:run(connection)
    local system = rawget(_G, "RoadGarbageSystem")
    if system == nil then
        return
    end

    if self.action == RoadGarbageEvent.ACTION_REQUEST then
        if g_server ~= nil and connection ~= nil
            and connection.getIsServer ~= nil and not connection:getIsServer() then
            system:sendFullState(connection)
        end
        return
    end

    -- Only the authoritative server may add or remove map garbage. Never accept
    -- object mutations sent by a client.
    if g_server ~= nil and connection ~= nil
        and connection.getIsServer ~= nil and not connection:getIsServer() then
        return
    end

    if self.action == RoadGarbageEvent.ACTION_ADD then
        system:applySpawnLocal(
            self.objectId, self.x, self.z, self.rotY, self.modelIndex
        )
    elseif self.action == RoadGarbageEvent.ACTION_REMOVE then
        system:removeLocal(self.objectId)
    elseif self.action == RoadGarbageEvent.ACTION_CLEAR then
        system:clearLocal()
    end
end

function RoadGarbageEvent.sendRequest()
    if g_server == nil and g_client ~= nil
        and g_client.getServerConnection ~= nil
        and g_client:getServerConnection() ~= nil then
        g_client:getServerConnection():sendEvent(
            RoadGarbageEvent.new(RoadGarbageEvent.ACTION_REQUEST)
        )
    end
end

