#pragma once
#include <string>
#include <unordered_map>
#include <glm/glm.hpp>
#include <GL/glew.h>

class Shader {
public:
    Shader();
    ~Shader();

    bool LoadFromFile(const std::string& vertexPath, const std::string& fragmentPath);
    bool LoadFromSource(const std::string& vertexSrc, const std::string& fragmentSrc);
    void Use() const;
    GLuint GetID() const;
    void Clear();

    // === Uniform Setters ===
    inline void SetBool(const std::string& name, bool value) {
        glUniform1i(GetUniformLocation(name), static_cast<int>(value));
    }
    inline void SetInt(const std::string& name, int value) {
        glUniform1i(GetUniformLocation(name), value);
    }
    inline void SetFloat(const std::string& name, float value) {
        glUniform1f(GetUniformLocation(name), value);
    }
    inline void SetVec2(const std::string& name, const glm::vec2& value) {
        glUniform2fv(GetUniformLocation(name), 1, &value[0]);
    }
    inline void SetVec3(const std::string& name, const glm::vec3& value) {
        glUniform3fv(GetUniformLocation(name), 1, &value[0]);
    }
    inline void SetVec4(const std::string& name, const glm::vec4& value) {
        glUniform4fv(GetUniformLocation(name), 1, &value[0]);
    }
    inline void SetMat4(const std::string& name, const glm::mat4& mat) {
        glUniformMatrix4fv(GetUniformLocation(name), 1, GL_FALSE, &mat[0][0]);
    }

private:
    GLuint id = 0;
    std::unordered_map<std::string, GLint> uniformCache;

    GLint GetUniformLocation(const std::string& name);
    std::string ReadFile(const std::string& path);
    GLuint Compile(GLenum type, const std::string& source);
};
