#include "assets.h"
#include "rres.h"
#include "rres-raylib.h"

const char textureAssetPaths[TEXTURE_ASSET_COUNT][ASSET_PATH_MAX] = {
	"icon.png",
	"icon128.png",
	"icon64.png",
	"gyroscope.png",
	"skyTexture.png"
};

const char modelAssetPaths[MODEL_ASSET_COUNT][ASSET_PATH_MAX] = {
	"antifaShip.obj",
	"soldato.obj",
	"caporale.obj",
	"sergente.obj",
	"maresciallo.obj",
	"generale.obj",
	"mussolini.obj",
	"guidedMissile.obj",
	"missile.obj",
	"gyroscope.obj",
	"sky.obj"
};

// Some models have textures and other stuff to be set.
void configModelAssets(Assets * assets) {
	// Gyroscope
	SetMaterialTexture(
		&assets->models[GYROSCOPE_ASSET].materials[0],
		MATERIAL_MAP_DIFFUSE,
		assets->textures[GYROSCOPE_TEXTURE_ASSET]
	);

	// Sky.
	SetMaterialTexture(
		&assets->models[SKY_ASSET].materials[0],
		MATERIAL_MAP_DIFFUSE,
		assets->textures[SKY_TEXTURE_ASSET]
	);
}

void loadTextureAsset(Assets * assets, int index, rresCentralDir dir, const char * filePath) {
	// Load and unpack.
	rresResourceChunk chunk = rresLoadResourceChunk(filePath, rresGetResourceId(dir, textureAssetPaths[index]));
	int result = UnpackResourceChunk(&chunk);

	if (result == 0) {
		Image image = LoadImageFromResource(chunk);

		if (image.data == NULL) {
			TraceLog(LOG_WARNING, "Issue loading image: %s", textureAssetPaths[index]);
		} else {
			// Load texture and unload image.
			assets->textures[index] = LoadTextureFromImage(image);
			UnloadImage(image);
		}
	} else {
		TraceLog(LOG_WARNING, "Issue unpacking resource: %s", textureAssetPaths[index]);
	}

	rresUnloadResourceChunk(chunk);
}

void loadModelAsset(Assets * assets, int index, rresCentralDir dir, const char * filePath) {
	// Model chunk.
	rresResourceChunk modelChunk = rresLoadResourceChunk(filePath, rresGetResourceId(dir, modelAssetPaths[index]));

	// Material chunk.
	char materialPath[ASSET_PATH_MAX];
	snprintf(materialPath, ASSET_PATH_MAX, "%s.mtl", GetFileNameWithoutExt(modelAssetPaths[index]));
	rresResourceChunk materialChunk = rresLoadResourceChunk(filePath, rresGetResourceId(dir, materialPath));

	int result = UnpackResourceChunk(&modelChunk);

	// Load and create temp file for model.
	if (result == 0) {
		unsigned int dataSize;
		void * data = LoadDataFromResource(modelChunk, &dataSize);

		if (data == NULL || data <= 0) {
			TraceLog(LOG_WARNING, "Issues loading model: %s", modelAssetPaths[index]);
		} else {
			FILE * tempFile = fopen("temp.obj", "wb");
			fwrite(data, 1, dataSize, tempFile);
			MemFree(data);
			fclose(tempFile);
		}
	} else {
		TraceLog(LOG_WARNING, "Issue unpacking resource: %s", modelAssetPaths[index]);
	}

	result = UnpackResourceChunk(&materialChunk);

	// Load and create temp file for material.
	if (result == 0) {
		unsigned int dataSize;
		void * data = LoadDataFromResource(materialChunk, &dataSize);

		if (data == NULL || data <= 0) {
			TraceLog(LOG_WARNING, "Issues loading material: %s", materialPath);
		} else {
			FILE * tempFile = fopen(materialPath, "wb");
			fwrite(data, 1, dataSize, tempFile);
			MemFree(data);
			fclose(tempFile);
		}
	} else {
		TraceLog(LOG_WARNING, "Issue unpacking resource: %s", materialPath);
	}

	// Load model now (:
	assets->models[index] = LoadModel("temp.obj");

	// Remove temp files.
	remove("temp.obj");
	remove(materialPath);

	// Free this bloody shit.
	rresUnloadResourceChunk(modelChunk);
	rresUnloadResourceChunk(materialChunk);
}

void LoadAssets(Assets * assets) {
	int i;

	TraceLog(LOG_INFO, "Loading assets");

	const char * filePath = "assets.rres";

	// Load centeral dir.
	rresCentralDir dir = rresLoadCentralDirectory(filePath);

	if (dir.count == 0)
		TraceLog(LOG_WARNING, "No central directory available in %s", filePath);

	// Textures first because models can use textures.

	// Textures.
	for (i = 0; i < TEXTURE_ASSET_COUNT; ++i)
		loadTextureAsset(assets, i, dir, filePath);

	// Models.
	for (i = 0; i < MODEL_ASSET_COUNT; ++i)
		loadModelAsset(assets, i, dir, filePath);

	rresUnloadCentralDirectory(dir);
	configModelAssets(assets);
	TraceLog(LOG_INFO, "Assets loaded");
}

void unloadAssets(Assets * assets) {
	int i;

	// Textures.
	for (i = 0; i < TEXTURE_ASSET_COUNT; ++i)
		UnloadTexture(assets->textures[i]);

	// Models.
	for (i = 0; i < MODEL_ASSET_COUNT; ++i)
		UnloadModel(assets->models[i]);

	TraceLog(LOG_INFO, "Assets unloaded");
}