#pragma once

#include <string>
#include <map>
#include <vector>
#include <memory>
#include <glad/glad.h>
#include <glm/glm.hpp>
#include <glm/gtc/type_ptr.hpp>

class ShaderProgram;
class CompleteShader;
class RenderSystem;

class Shader2D;
class SolidColorShader;
class TextShader;

/**
 * @brief 着色器管理器 - 负责着色器的编译、链接和管理 (C++ 静态工具类实现)
 */
class VIVID_2D_MYDLL_API ShaderManagement
{
private:
    // 禁止实例化
    ShaderManagement() = delete;
    ShaderManagement(const ShaderManagement&) = delete;
    ShaderManagement& operator=(const ShaderManagement&) = delete;

public:
    /**
     * @brief 着色器程序缓存映射，按名称存储已编译的着色器程序
     * 使用 std::unique_ptr 来管理 ShaderProgram 的生命周期
     */
    static std::map<std::string, std::unique_ptr<ShaderProgram>> s_shaderMap;

    /**
     * @brief 着色器列表，按顺序存储所有着色器源代码定义
     * 注意：在 C++ 中，静态初始化列表通常放在 .cpp 文件中。
     * 这里使用 std::vector<std::unique_ptr<CompleteShader>> 来管理多态对象。
     */
    static std::vector<std::unique_ptr<CompleteShader>> s_shaderList;

    /**
     * @brief 默认着色器程序
     */
    static ShaderProgram* s_defaultProgram;

    // --- 核心管理方法 ---

    /**
     * @brief 编译所有注册的着色器
     */
    static void compileAllShaders();

    /**
     * @brief 清理所有着色器资源
     */
    static void cleanup();

    // --- Getter 方法 ---

    /**
     * @brief 获取默认着色器程序
     */
    static ShaderProgram* getDefaultProgram();

    /**
     * @brief 按名称获取着色器程序
     */
    static ShaderProgram* getShaderProgram(const std::string& name);

    static void setUniformInt(ShaderProgram* program, const std::string& name, GLint value);
    static void setUniformFloat(ShaderProgram* program, const std::string& name, GLfloat value);

    // Vec2/Vec3/Vec4 (使用 GLM)
    static void setUniformVec2(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y);
    static void setUniformVec2(ShaderProgram* program, const std::string& name, const glm::vec2& vec);
    static void setUniformVec3(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z);
    static void setUniformVec3(ShaderProgram* program, const std::string& name, const glm::vec3& vec);
    static void setUniformVec4(ShaderProgram* program, const std::string& name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
    static void setUniformVec4(ShaderProgram* program, const std::string& name, const glm::vec4& vec);

    // Mat3 (使用 GLM)
    static void setUniformMat3(ShaderProgram* program, const std::string& name, const glm::mat3& matrix);

private:
    /**
     * @brief 编译单个完整的着色器程序
     */
    static void compileShaderProgram(const CompleteShader* completeShader);

    /**
     * @brief 设置默认着色器的uniform值
     */
    static void setupDefaultUniforms(ShaderProgram* program);

    /**
     * @brief 编译着色器
     */
    static GLuint compileShader(GLenum type, const std::string& source, const std::string& shaderName);

    /**
     * @brief 链接着色器程序
     */
    static GLuint linkProgram(GLuint vertexShaderId, GLuint fragmentShaderId, const std::string& programName);

    /**
     * @brief 自定义程序验证方法
     */
    static void validateProgram(GLuint programId, const std::string& programName);
};