#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 apVertex
{
	Vec3 pos;
	Vec3 normal;
	Vec2 uv;
	u32 color;
} apVertex;

ArrayType(apVertex);

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

typedef struct apMatProps
{
	Vec4 ambient;
	Vec4 specular;
	f32 shininess;
} apMatProps;

typedef struct apMatTextures
{
	u32 albedo;
	u32 ambient;
	u32 specular;
} apMatTextures;

typedef struct apMaterial
{
	apMatProps 		props;
	apMatTextures tex;
} apMaterial;

ArrayType(apMaterial);

typedef struct apMesh
{
	u64							mat_idx;
	u64							start_idx;
	u64							length;
} apMesh;

ArrayType(apMesh);

typedef struct apTexData
{
	rawptr bytes;
	u32		 w;
	u32		 h;
	u32		 ch;
} apTexData;

ArrayType(apTexData);

typedef struct apModel
{
	apVertexArray 	 vertices;
	u32Array			 indices;
	apMeshArray 	 meshes;
	apMaterialArray materials;
	apTexDataArray textures;
	m3d_t						*m3d;
} apModel;

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;
		apModel *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 apModel *apParseModel(u8 *data);
static void apFreeModel(apModel *model);
