#include "DeerRender/Shader.h"
#include "Deer/Log.h"
#include <unordered_map>

namespace Deer {
	namespace ShaderManager {
		struct ShaderManagerContainer {
			Path shader_name;
			Shader* shader_data = nullptr;
		};

        size_t minShaderId = 1;
        ShaderManagerContainer shaders[SCENE_MAX_SHADER_COUNT]{};
		std::unordered_map<Path, size_t> shader_name_id;
	}

	void ShaderManager::unloadAllShaders() {
		for (uint16_t i = 0; i < minShaderId; i++) {
			delete shaders[i].shader_data;
			shaders[i].shader_data = nullptr;
		}
		shader_name_id.clear();

		shader_name_id["NULL"] = 0;
		shaders[0].shader_name = nullptr;
		shaders[0].shader_name = "NULL";
		minShaderId = 1;
	}

	uint16_t ShaderManager::loadShader(const Path& name) {
		if (shader_name_id.contains(name))
			return shader_name_id[name];

		
		ShaderData shaderData;
		DataStore::loadShader(shaderData, name);
		
		return loadShader(shaderData, name);
	}

	uint16_t ShaderManager::loadShader(const ShaderData& data, const Path& name) {
		if (minShaderId >= SCENE_MAX_SHADER_COUNT) {
			DEER_CORE_ERROR("Max shader loaded into a scene");
			return -1;
		}

		uint16_t shaderId = minShaderId;
		minShaderId++;

		shaders[shaderId].shader_data = Shader::create(data.vertexShader, data.fragmentShader);
		shaders[shaderId].shader_name = name;

		return shaderId;
	}

	Shader& ShaderManager::getShader(uint16_t shaderId) {
		DEER_CORE_ASSERT(shaderId >= 0 && shaderId < minShaderId, "Invalid shader id, id is not loaded");

		return *shaders[shaderId].shader_data;
	}

	const Path& ShaderManager::getShaderName(uint16_t shaderId) {
		DEER_CORE_ASSERT(shaderId >= 0 && shaderId < minShaderId, "Invalid shader id, id is not loaded");

		return shaders[shaderId].shader_name;
	}
}