#pragma once

// ::Renderer::Declarations::Header::

typedef struct rDescHandle rDescHandle;

// @requirement rRenderBufferType type
// @requirement u32 size
// @requirement u32 index
typedef struct rRenderBuffer rRenderBuffer;

// @requirement rTextureBufferType type
// @requirement u32 width
// @requirement u32 height
// @requirement u32 index
typedef struct rTextureBuffer rTextureBuffer;

typedef struct rPushConst rPushConst;
typedef struct rShaderGlobals rShaderGlobals;

// ::Renderer::Enums::Header::

typedef enum Pipeline_e 
{
	R_PIPELINE_CUBE,
	R_PIPELINE_GUI,

	R_PIPELINE_MAX,
} rPipelineHandle;

typedef enum PipelineType_e
{
	rPT_GRAPHICS = 0,
	rPT_COMPUTE = 1,
} rPipelineType;

typedef enum RenderBufferType_e
{
	rRBT_NONE 	 			= 0x0000,
	rRBT_VERTEX  			= 0x0001,
	rRBT_INDEX 	 			= 0x0002,
	rRBT_UNIFORM 			= 0x0004,
	rRBT_STORAGE 			= 0x0008,
	rRBT_HOST 				= 0x0010,
	rRBT_STAGING 			= 0x0020,
	rRBT_HOST_VERTEX  = rRBT_HOST | rRBT_VERTEX,
	rRBT_HOST_INDEX   = rRBT_HOST | rRBT_INDEX,
	rRBT_HOST_UNIFORM = rRBT_HOST | rRBT_UNIFORM,
	rRBT_HOST_STORAGE = rRBT_HOST | rRBT_STORAGE,
} rRenderBufferType;

typedef enum TextureBufferType_e
{
	rTBT_NONE 		= 0x0000,
	rTBT_IMAGE 	= 0x0001,
	rTBT_SAMPLER = 0x0002,
} rTextureBufferType;

typedef enum VertexAttrType_e
{
	rVAT_VERTEX = 0,
	rVAT_COLOR = 1,
} rVertexAttrType;

// ::Renderer::Types::Header::

typedef struct rUIVertex
{
	Vec2 p0;
	Vec2 p1;
	Vec4 col;
	u32  tex_idx;
} rUIVertex;

typedef struct rUploadQueue
{
	union
	{
		rRenderBuffer 	**queued_buffers;
		rTextureBuffer **queued_textures;
		rawptr 				*queued_ptrs;
	};
	rawptr 		*data;
	TicketMut ticket_mut;
	Mut 			mut;
	JobQueue  job_queue;
} rUploadQueue;

typedef struct rMappedBuffer
{
	rawptr ptr;
	u32		 elem_count;
} rMappedBuffer;

typedef rawptr rBuffer;

// ::Renderer::Initialization::Header::

b32 rInit();
void rDestroy();

// ::Renderer::Buffers::Header::

static b32 rBufferMap();
static rDescHandle rTextureLoad(TextureAsset asset_id);
static void rTextureUnload(rDescHandle handle);
static void rBufferBindVertex(rRenderBuffer *buffer);
static void rBufferBindIndex(rRenderBuffer *buffer);
static rawptr rBufferGUIVertMapping();
static rawptr rBufferGUIIdxMapping();
static void rBufferBindGUIVertex();
static void rBufferBindGUIIndex();

// ::Renderer::Uniforms::Header:: 
// ::Renderer::PushConstants::Header::

static void rViewportSize(Vec2 *size);
static void rGlobalUniformSet(rShaderGlobals *globals);
static void rPushConstantsSet(rPushConst *pc);

// ::Renderer::Config::Header::

static void rResolutionSet(u32 x, u32 y);

// ::Renderer::Rendering::Header::

static b32 rFrameBegin();
static b32 rFrameFinish();
static void rDrawIndexed(u32 index_count, u32 instance_count);
static void rPipelineBind(rPipelineHandle handle, rPipelineType type);

// ::Renderer::Includes::Header::

#if STG_VULKAN_RENDERER
#include "renderer_vulkan.h"
#endif
