#pragma once

// ::Assets::Macros::Header::

#define FILE_VERSION 3U

#define CreateMagicValue(a, b, c, d) ((u32)(d << 24) | (u32)(c << 16) | (u32)(b << 8) | (u32)(a))

// ::Assets::Globals::Header::
#include "codegen_assets.h"

// ::Assets::Types::Header::

typedef struct Vertex
{
	f32 v_x, v_y, v_z;
	f32 n_x, n_y, n_z;
	f32 uv_x, uv_y;
	u32 color;
} Vertex;

typedef struct Image
{
	rawptr data;
	i32		 w;
	i32		 h;
	i32		 ch;
} Image;

typedef struct Material
{
	Vec4 color;
	Vec4 ambient;
	Vec4 specular;
	Vec4 emission;
	f32 shininess;
} Material;

typedef struct ModelIndex
{
	u32 material;
	u32 start;
	u32 count;
} ModelIndex;

typedef struct Model
{
	struct 
	{
		Vertex *data;
		u64 		count;
	} vertex;
	struct
	{
		u32 *data;
		u64  count;
	} index;
	struct 
	{
		Material *data;
		u64			 count;
	} material;
	struct
	{
		ModelIndex *data;
		u64					count;
	} offset;
} Model;

typedef struct TexMeta
{
	u32 w;
	u32 h;
	u32 ch;
} TexMeta;

typedef struct ModelMeta
{
	u64 i_count;
} ModelMeta;

typedef struct AssetTag
{
	u32 tag_id;
	f32 value;
} AssetTag;

typedef enum AssetType_e
{
	AT_NONE,
	AT_SHADER,
	AT_TEXTURE,
	AT_MODEL,
}	AssetType;

typedef struct Asset
{
	union
	{
		const char *cstr;
		u8 			 *bytes;
		Model *model;
	};
	union
	{
		TexMeta texture_meta;
		ModelMeta model_meta;
	};
	u64 hash;
	u64	len;
	AssetType type;
} Asset;

typedef struct AssetFile
{
	union
	{
		TexMeta 	texture_meta;
		ModelMeta model_meta;
	};
	u64 hash;
	u64 data_offset;
	u64 len;
	AssetType type;
} AssetFile;

typedef struct FileHeader
{
	u32 magic_num;
	u32 version;
	u32 asset_counts;
	u64 asset_offset;
} FileHeader;

// ::Assets::Init::Functions::Header::

static void apInit();

// ::Assets::Loading::Functions::Header::

static Asset apLoad(c8 *str);
static Asset apLoadS8(String8 str);
static Asset apLoadWithHash(u64 hash);
static void  apUnload(c8 *str);
static void  apUnloadS8(String8 str);
static void  apUnloadWithHash(u64 hash);
static u64	 apAssetIndex(c8 *str);
static Asset *apAssetSearch(u64 hash);

// ::Assets::Util::Functions::Header::

// TODO(MA): Implement async asset handling
static inline b32 apMarkUnloaded(c8 *str);
static inline void apMarkLoaded(c8 *str);

// ::Assets::Images::Header::

static Image apLoadImage(rawptr data, u64 len);
static void apFreeImage(Image *image);

// ::Assets::Models::Functions::Header::

static Model *apParseModel(u8 *data);
static void apFreeModel(Model *model);
