#pragma once

#include "pxl8_types.h"

#ifdef __cplusplus
extern "C" {
#endif

#define PXL8_PROTOCOL_VERSION 1
#define PXL8_MAX_SNAPSHOT_ENTITIES 256
#define PXL8_MAX_SNAPSHOT_EVENTS 32
#define PXL8_COMMAND_PAYLOAD_SIZE 64
#define PXL8_EVENT_PAYLOAD_SIZE 15

typedef enum pxl8_msg_type {
    PXL8_MSG_NONE = 0,
    PXL8_MSG_CONNECT,
    PXL8_MSG_DISCONNECT,
    PXL8_MSG_INPUT,
    PXL8_MSG_COMMAND,
    PXL8_MSG_SNAPSHOT,
    PXL8_MSG_EVENT
} pxl8_msg_type;

typedef struct pxl8_msg_header {
    u32 sequence;
    u16 size;
    u8 type;
    u8 version;
} pxl8_msg_header;

typedef enum pxl8_cmd_type {
    PXL8_CMD_NONE = 0,
    PXL8_CMD_SPAWN_ENTITY,
} pxl8_cmd_type;

typedef struct pxl8_input_msg {
    u32 buttons;
    f32 look_dx;
    f32 look_dy;
    f32 move_x;
    f32 move_y;
    f32 yaw;
    u64 tick;
    u64 timestamp;
} pxl8_input_msg;

typedef struct pxl8_command_msg {
    u16 cmd_type;
    u8 payload[PXL8_COMMAND_PAYLOAD_SIZE];
    u16 payload_size;
    u64 tick;
} pxl8_command_msg;

typedef struct pxl8_entity_state {
    u64 entity_id;
    u8 userdata[56];
} pxl8_entity_state;

typedef struct pxl8_event_msg {
    u8 event_type;
    u8 payload[PXL8_EVENT_PAYLOAD_SIZE];
} pxl8_event_msg;

typedef struct pxl8_snapshot_header {
    u16 entity_count;
    u16 event_count;
    u64 player_id;
    u64 tick;
    f32 time;
} pxl8_snapshot_header;

size_t pxl8_protocol_serialize_header(const pxl8_msg_header* msg, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_header(const u8* buf, size_t len, pxl8_msg_header* msg);

size_t pxl8_protocol_serialize_input(const pxl8_input_msg* msg, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_input(const u8* buf, size_t len, pxl8_input_msg* msg);

size_t pxl8_protocol_serialize_command(const pxl8_command_msg* msg, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_command(const u8* buf, size_t len, pxl8_command_msg* msg);

size_t pxl8_protocol_serialize_entity_state(const pxl8_entity_state* state, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_entity_state(const u8* buf, size_t len, pxl8_entity_state* state);

size_t pxl8_protocol_serialize_event(const pxl8_event_msg* msg, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_event(const u8* buf, size_t len, pxl8_event_msg* msg);

size_t pxl8_protocol_serialize_snapshot_header(const pxl8_snapshot_header* hdr, u8* buf, size_t len);
size_t pxl8_protocol_deserialize_snapshot_header(const u8* buf, size_t len, pxl8_snapshot_header* hdr);

#ifdef __cplusplus
}
#endif
