#pragma once

#include "pxl8_io.h"
#include "pxl8_rng.h"
#include "pxl8_types.h"

#define PXL8_REPLAY_MAGIC 0x31525850
#define PXL8_REPLAY_VERSION 1

#define PXL8_REPLAY_CHUNK_KEYFRAME    0x01
#define PXL8_REPLAY_CHUNK_INPUT       0x02
#define PXL8_REPLAY_CHUNK_AUDIO_EVENT 0x03
#define PXL8_REPLAY_CHUNK_END         0xFF

#define PXL8_REPLAY_FLAG_HAS_PALETTE  (1 << 0)
#define PXL8_REPLAY_FLAG_HAS_GLOBALS  (1 << 1)

typedef struct pxl8_replay pxl8_replay;

typedef struct pxl8_replay_header {
    u32 magic;
    u32 version;
    u32 flags;
    u32 keyframe_interval;
    u32 total_frames;
    u32 width;
    u32 height;
    u32 reserved;
} pxl8_replay_header;

typedef struct pxl8_keyframe {
    u32 frame_number;
    f32 time;
    u32 rng_state;
    u8 keys_down[32];
    u8 mouse_buttons;
    i16 mouse_x;
    i16 mouse_y;
    u8 flags;
} pxl8_keyframe;

typedef struct pxl8_input_delta {
    u32 frame_number;
    u8 key_event_count;
    u8 mouse_flags;
} pxl8_input_delta;

typedef struct pxl8_audio_event {
    u32 frame_number;
    u8 event_type;
    u8 context_id;
    u8 note;
    f32 volume;
} pxl8_audio_event;

#ifdef __cplusplus
extern "C" {
#endif

pxl8_replay* pxl8_replay_create(const char* path, u32 keyframe_interval);
pxl8_replay* pxl8_replay_create_buffer(u32 keyframe_interval, u32 max_keyframes);
pxl8_replay* pxl8_replay_open(const char* path);
void pxl8_replay_destroy(pxl8_replay* r);

bool pxl8_replay_is_recording(pxl8_replay* r);
bool pxl8_replay_is_playing(pxl8_replay* r);
u32 pxl8_replay_get_frame(pxl8_replay* r);
u32 pxl8_replay_get_total_frames(pxl8_replay* r);

void pxl8_replay_write_keyframe(pxl8_replay* r, u32 frame, f32 time, pxl8_rng* rng, pxl8_input_state* input);
void pxl8_replay_write_input(pxl8_replay* r, u32 frame, pxl8_input_state* prev, pxl8_input_state* curr);
void pxl8_replay_write_audio_event(pxl8_replay* r, u32 frame, u8 event_type, u8 context_id, u8 note, f32 volume);
void pxl8_replay_close(pxl8_replay* r);

bool pxl8_replay_seek_frame(pxl8_replay* r, u32 frame);
bool pxl8_replay_read_frame(pxl8_replay* r, pxl8_input_state* input_out);
bool pxl8_replay_get_keyframe(pxl8_replay* r, u32 frame, pxl8_keyframe* out);
void pxl8_replay_apply_keyframe(pxl8_replay* r, pxl8_keyframe* kf, pxl8_rng* rng, pxl8_input_state* input);

bool pxl8_replay_export(pxl8_replay* r, const char* path);

#ifdef __cplusplus
}
#endif
