const std = @import("std");
const znet = @import("znet");
const bufzilla = @import("bufzilla");

const shared = @import("shared");
const server = @import("server.zig");

pub fn spawn(chunk: *shared.chunk.Chunk(), comptime T: type, allocator: std.mem.Allocator, value: T) !void {
    std.debug.assert(value.id == shared.entity.INVALID_ID);

    const id = server.next_entity_id;
    server.next_entity_id += 1;

    var entity = value;
    entity.id = id;

    inline for (@typeInfo(shared.chunk.Chunk()).@"struct".fields) |field| {
        if (field.type == shared.chunk.Storage(T)) {
            try @field(chunk, field.name).items.append(allocator, entity);
            break;
        }
    }

    // serialize entity
    var buffer: [128]u8 = undefined;
    var fixed = std.io.Writer.fixed(&buffer);

    const msg = shared.protocol.makeSpawnMessage(T, entity);

    var writer = bufzilla.Writer.init(&fixed);
    try writer.writeAny(msg);

    const encoded = fixed.buffered();

    const packet = try znet.Packet.init(encoded, 0, .reliable);
    var iterator = server.host.iterPeers();

    while (iterator.next()) |peer| {
        if (peer.state() == .connected) {
            try peer.send(packet);
        }
    }
}
