
// ::Assets::Globals::Start::

u8 ASSET_PACK[] = 
{	
	#embed "../assets.sgp" 
};

static FileHeader File_Header = {0};

static AssetFile Texture_Assets[TEXTURE_ASSET_MAX];
static Asset 		 Texture_Asset_Lookup[TEXTURE_ASSET_MAX];

static AssetFile Shader_Assets[SHADER_ASSET_MAX];
static Asset		 Shader_Asset_Lookup[SHADER_ASSET_MAX];

// TODO(MA): Implement async asset handling
static u32			 Shader_Asset_Ref_Count[SHADER_ASSET_MAX];
static u32			 Texture_Asset_Ref_Count[TEXTURE_ASSET_MAX];

static b32 ASSET_HEADER_LOADED = false;


// ::Assets::Global::End::



// ::Assets::Init::Functions::Start::

static void LoadAssetPackHeader()
{
	MemCpy(&File_Header, ASSET_PACK, sizeof(FileHeader));

	Assert(File_Header.magic_num == CreateMagicValue('s', 't', 'e', 'g'), "Magic value is incorrect");

	MemCpy(Texture_Assets, &ASSET_PACK[File_Header.asset_offsets[TEXTURE_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[TEXTURE_ASSET]);

	MemCpy(Shader_Assets, &ASSET_PACK[File_Header.asset_offsets[SHADER_ASSET]], sizeof(AssetFile) * File_Header.asset_counts[SHADER_ASSET]);

	ASSET_HEADER_LOADED = true;
}

// ::Assets::Init::Functions::End::



// ::Assets::Loading::Functions::Start::

static Asset AssetPackLoadTexture(TextureAsset asset_id)
{
	if (!ASSET_HEADER_LOADED)
	{
		LoadAssetPackHeader();
	}

	Assert(asset_id < i32(TEXTURE_ASSET_MAX), "LoadTextureAsset failure: asset_id is higher than TEXTURE_ASSET_MAX");

	Asset asset = Texture_Asset_Lookup[asset_id];

	if (asset.bytes == NULL)
	{
		AssetFile *asset_info = Texture_Assets + asset_id;
		u8 *img = FLMemAlloc(asset_info->len);
		MemCpy(img, &ASSET_PACK[asset_info->data_offset], asset_info->len);

		int x, y, ch;
		asset.bytes = stbi_load_from_memory(img, asset_info->len, &x, &y, &ch, 4);

		asset.len = asset_info->len;
		asset.texture_meta.w = u32(x);
		asset.texture_meta.h = u32(y);

		Texture_Asset_Lookup[asset_id] = asset;

		FLMemFree(img);
	}

	return asset;
}

static Asset AssetPackLoadShader(ShaderAsset asset_id)
{
	if (!ASSET_HEADER_LOADED)
	{
		LoadAssetPackHeader();
	}

	Assert(asset_id < SHADER_ASSET_MAX, "LoadShaderAsset failure: asset_id is higher than SHADER_ASSET_MAX");

	Asset asset = Shader_Asset_Lookup[asset_id];
	if (asset.bytes == NULL)
	{
		AssetFile *asset_info = Shader_Assets + asset_id;
		asset.bytes = FLMemAlloc(asset_info->len);
		MemCpy(asset.bytes, &ASSET_PACK[asset_info->data_offset], asset_info->len);
		asset.len = asset_info->len;
		Shader_Asset_Lookup[asset_id] = asset;
	}

	return asset;
}

static void AssetPackUnloadTexture(Asset asset)
{
	Assert(asset.bytes != NULL, "UnloadTextureAsset assert failure: ptr is NULL");

	for (u32 i = 0; i < TEXTURE_ASSET_MAX; i++)
	{
		if (asset.bytes == Texture_Asset_Lookup[i].bytes)
		{
			Texture_Asset_Lookup[i].bytes = NULL;
			Texture_Asset_Lookup[i].len = 0;
			stbi_image_free(asset.bytes);

			break;
		}
	}
}

static void AssetPackUnloadShader(Asset asset)
{
	Assert(asset.bytes != NULL, "UnloadShaderAsset assert failure: ptr is NULL");

	for (u32 i = 0; i < SHADER_ASSET_MAX; i++)
	{
		if (asset.bytes == Shader_Asset_Lookup[i].bytes)
		{
			Shader_Asset_Lookup[i].bytes = NULL;
			Shader_Asset_Lookup[i].len = 0;
			FLMemFree(asset.bytes);

			break;
		}
	}
}

// ::Assets::Loading::Functions::End::
