MudExtraParticleEvent = {}
local MudExtraParticleEvent_mt = Class(MudExtraParticleEvent, Event)
InitEventClass(MudExtraParticleEvent, "MudSystemPhysics.MudExtraParticleEvent")

MudExtraParticleEvent.CHANNEL_MUD = 1
MudExtraParticleEvent.CHANNEL_FIELD = 2

function MudExtraParticleEvent.emptyNew()
    return Event.new(MudExtraParticleEvent_mt)
end

function MudExtraParticleEvent.new(vehicle, wheelIndex, channel, isActive, x, y, z, burst)
    local self = MudExtraParticleEvent.emptyNew()
    self.vehicle = vehicle
    self.wheelIndex = wheelIndex or 0
    self.channel = channel or 0
    self.isActive = isActive == true
    self.x = x or 0
    self.y = y or 0
    self.z = z or 0
    self.burst = burst == true
    return self
end

function MudExtraParticleEvent:readStream(streamId, connection)
    self.vehicle = NetworkUtil.readNodeObject(streamId)
    self.wheelIndex = streamReadUInt8(streamId)
    self.channel = streamReadUInt8(streamId)
    self.isActive = streamReadBool(streamId)
    self.x = streamReadFloat32(streamId)
    self.y = streamReadFloat32(streamId)
    self.z = streamReadFloat32(streamId)
    self.burst = streamReadBool(streamId)
    self:run(connection)
end

function MudExtraParticleEvent:writeStream(streamId, connection)
    NetworkUtil.writeNodeObject(streamId, self.vehicle)
    streamWriteUInt8(streamId, self.wheelIndex or 0)
    streamWriteUInt8(streamId, self.channel or 0)
    streamWriteBool(streamId, self.isActive == true)
    streamWriteFloat32(streamId, self.x or 0)
    streamWriteFloat32(streamId, self.y or 0)
    streamWriteFloat32(streamId, self.z or 0)
    streamWriteBool(streamId, self.burst == true)
end

function MudExtraParticleEvent:run(connection)
    -- Particle state is authoritative on the server. Never accept a forged
    -- client event that could make every peer create emitters indefinitely.
    if connection ~= nil and not connection:getIsServer() then
        return
    end

    if self.vehicle == nil then
        return
    end

    if self.channel == MudExtraParticleEvent.CHANNEL_MUD then
        if MudPhysics ~= nil and MudPhysics.applyNetworkExtraParticles ~= nil then
            MudPhysics:applyNetworkExtraParticles(
                self.vehicle, self.wheelIndex, self.isActive,
                self.x, self.y, self.z, self.burst
            )
        end
    elseif self.channel == MudExtraParticleEvent.CHANNEL_FIELD then
        if FieldGroundMudPhysics ~= nil and FieldGroundMudPhysics.applyNetworkExtraParticles ~= nil then
            FieldGroundMudPhysics:applyNetworkExtraParticles(
                self.vehicle, self.wheelIndex, self.isActive,
                self.x, self.y, self.z, self.burst
            )
        end
    end
end

function MudExtraParticleEvent.send(vehicle, wheelIndex, channel, isActive, x, y, z, burst)
    if g_server == nil or vehicle == nil or wheelIndex == nil then
        return
    end

    -- A listen server also owns a rendering client, so apply locally once.
    if g_client ~= nil then
        if channel == MudExtraParticleEvent.CHANNEL_MUD
            and MudPhysics ~= nil and MudPhysics.applyNetworkExtraParticles ~= nil then
            MudPhysics:applyNetworkExtraParticles(vehicle, wheelIndex, isActive, x, y, z, burst)
        elseif channel == MudExtraParticleEvent.CHANNEL_FIELD
            and FieldGroundMudPhysics ~= nil and FieldGroundMudPhysics.applyNetworkExtraParticles ~= nil then
            FieldGroundMudPhysics:applyNetworkExtraParticles(vehicle, wheelIndex, isActive, x, y, z, burst)
        end
    end

    g_server:broadcastEvent(
        MudExtraParticleEvent.new(vehicle, wheelIndex, channel, isActive, x, y, z, burst),
        nil, nil, vehicle
    )
end
