#ifndef RENDERER_H
#define RENDERER_H

struct sys_window;

#define RENDERER_TEXTURE_MAX_WIDTH 16384
#define RENDERER_TEXTURE_MAX_HEIGHT 16384

typedef u32 vidx;

struct renderer_canvas;

/* ========================== *
 * Shaders
 * ========================== */

enum shader_kind {
    SHADER_NONE,
    SHADER_TEXTURE,

    NUM_SHADERS
};

struct texture_shader_parameters {
    struct renderer_handle texture_handle;  /* Overrides sprite */
    struct sprite_tag sprite;
};

PACK(struct texture_shader_vertex {
    struct v2 pos;
    struct v2 uv;
    u32 color;
});


/* ========================== *
 * Startup
 * ========================== */

struct renderer_startup_receipt { i32 _; };
struct renderer_startup_receipt renderer_startup(struct sys_window *window);

/* ========================== *
 * Canvas
 * ========================== */

struct renderer_canvas *renderer_canvas_alloc(void);

void renderer_canvas_release(struct renderer_canvas *canvas);

/* Set the canvas view xform to be used when presenting the canvas.
 * NOTE: `view` should be in row-major order.
 */
void renderer_canvas_set_view(struct renderer_canvas *canvas, struct xform view);

/* Pushes array of vertices based on `vertices_count` & `indices_count`.
 * Sets `vertices_out` and `indices_out` to start of the pushed arrays, to be filled out by the caller.
 * Returns the index of the first vertex. Each inserted index should be incremented by this.
 *
 * NOTE: This should be preceded by an `ensure_cmd` call to ensure that the correct vertex types
 * are being pushed.
 */
u32 renderer_canvas_push_vertices(struct renderer_canvas *canvas, u8 **vertices_out, vidx **indices_out, u32 vertices_count, u32 indices_count);

/* Checks the currently active draw command. Ensures a new command is created
 * if it doesn't match the expected type (otherwise the command can be re-used
 * for batching). */
void renderer_canvas_ensure_texture_cmd(struct renderer_canvas *canvas, struct texture_shader_parameters params);

void renderer_canvas_send_to_gpu(struct renderer_canvas *canvas);

void renderer_canvas_present(struct renderer_canvas **canvases, u32 canvases_count, struct v2 screen_size, struct rect viewport, i32 vsync);

/* ========================== *
 * Texture
 * ========================== */

struct renderer_handle renderer_texture_alloc(struct image_rgba data);
void renderer_texture_release(struct renderer_handle handle);
b32 renderer_texture_is_nil(struct renderer_handle handle);

#endif
