DiseaseGridSnapshotEvent = {}
local DiseaseGridSnapshotEvent_mt = Class(DiseaseGridSnapshotEvent, Event)
InitEventClass(DiseaseGridSnapshotEvent, "DiseaseGridSnapshotEvent")

function DiseaseGridSnapshotEvent.emptyNew()
    return Event.new(DiseaseGridSnapshotEvent_mt)
end

function DiseaseGridSnapshotEvent.new(cells, isFirst, isLast)
    local self = DiseaseGridSnapshotEvent.emptyNew()
    self.cells = cells or {}
    self.isFirst = isFirst == true
    self.isLast = isLast == true
    return self
end

local function writeCell(streamId, cell)
    streamWriteUInt16(streamId, math.max(0, tonumber(cell.x or 0) or 0))
    streamWriteUInt16(streamId, math.max(0, tonumber(cell.z or 0) or 0))
    streamWriteUIntN(streamId, math.max(0, math.min(3, tonumber(cell.severity or 0) or 0)), 2)
    streamWriteUIntN(streamId, math.max(0, math.min(15, tonumber(cell.threatId or 0) or 0)), 4)
    streamWriteUIntN(streamId, math.max(0, math.min(3, tonumber(cell.protection or 0) or 0)), 2)
end

local function readCell(streamId)
    return {
        x = streamReadUInt16(streamId),
        z = streamReadUInt16(streamId),
        severity = streamReadUIntN(streamId, 2),
        threatId = streamReadUIntN(streamId, 4),
        protection = streamReadUIntN(streamId, 2)
    }
end

function DiseaseGridSnapshotEvent:writeStream(streamId, _)
    streamWriteBool(streamId, self.isFirst == true)
    streamWriteBool(streamId, self.isLast == true)
    streamWriteUInt16(streamId, #self.cells)
    for _, cell in ipairs(self.cells) do
        writeCell(streamId, cell)
    end
end

function DiseaseGridSnapshotEvent:readStream(streamId, connection)
    self.isFirst = streamReadBool(streamId)
    self.isLast = streamReadBool(streamId)
    self.cells = {}

    local count = streamReadUInt16(streamId)
    for _ = 1, count do
        table.insert(self.cells, readCell(streamId))
    end

    self:run(connection)
end

function DiseaseGridSnapshotEvent:run(_)
    if DiseaseGrid ~= nil and DiseaseGrid.applyNetworkCellBatch ~= nil then
        DiseaseGrid:applyNetworkCellBatch(self.cells, self.isFirst == true)
    end

    if DiseaseCore ~= nil and DiseaseCore.onClientGridSnapshotChunk ~= nil then
        DiseaseCore:onClientGridSnapshotChunk(self.isFirst == true, self.isLast == true)
    end
end

function DiseaseGridSnapshotEvent.sendToConnection(connection, cells, isFirst, isLast)
    if connection ~= nil then
        connection:sendEvent(DiseaseGridSnapshotEvent.new(cells, isFirst, isLast))
    end
end
