#include "DeerRender/Shader.h"
#include "Deer/DataStore.h"

#include <unordered_map>

namespace Deer {
	namespace DataStore {
        std::unordered_map<std::string, std::string> preProcess(const std::string& source);
	}

	void DataStore::loadShader(ShaderData& shader_data, const Path& name) {
		Path realName;
		realName = name.string() + DEER_SHADER_EXTENSION;

		uint32_t size;
		uint8_t* data = DataStore::readFile(realName, &size);

        DataStore::loadFileData(DEER_SHADER_PATH, realName, &data, &size);

        std::string str_data((char*)data, size);
        
        DataStore::freeFileData(data);

        std::unordered_map<std::string, std::string> types = preProcess(str_data);

        shader_data.freeData();
        if (types.contains("vertex")) {
            shader_data.vertexShader = types["vertex"];
        }

        if (types.contains("fragment")) {
            shader_data.fragmentShader = types["fragment"];
        }
    }

	std::unordered_map<std::string, std::string> DataStore::preProcess(const std::string& source) {
		std::unordered_map<std::string, std::string> shaderSource;

		const std::string typeToken = "#type ";
		size_t pos = 0;

		while (pos < source.size()) {
			size_t typePos = source.find(typeToken, pos);
			if (typePos == std::string::npos) break;

			size_t typeEnd = source.find_first_of("\n\r", typePos);
			if (typeEnd == std::string::npos) break;

			std::string shaderType = source.substr(typePos + typeToken.size(), typeEnd - typePos - typeToken.size());
			size_t nextTypePos = source.find(typeToken, typeEnd);

			std::string shaderSourceStr = source.substr(typeEnd + 1, nextTypePos - typeEnd - 1);
			shaderSource[shaderType] = shaderSourceStr;

			pos = nextTypePos;
		}

		return shaderSource;
	}

}