#ifndef SHADER_HPP
#define SHADER_HPP

#include <open_engine/ref_scope.hpp>
#include <glm/glm.hpp>
#include <string>

namespace OpenEngine {
    class Shader
    {
        public:
            static Ref<Shader> Create(const std::string& shader_path);
            static Ref<Shader> Create(const std::string& name, const std::string& vertex_src, const std::string& frament_src);

            virtual ~Shader() = default;

            virtual const std::string& GetName() const = 0;

            virtual void Bind() const = 0;
            virtual void Unbind() const = 0;

            virtual void SetBool(const std::string &name, bool value) const = 0;
            virtual void SetInt(const std::string &name, int value) const = 0;
            virtual void SetIntArray(const std::string &name, int* values, uint32_t count) const = 0;
            virtual void SetFloat(const std::string &name, float value) const = 0;
            virtual void SetMat4(const std::string &name, const glm::mat4& value) const = 0;
            virtual void SetVec2(const std::string &name, const glm::vec2& value) const = 0;
            virtual void SetVec3(const std::string &name, const glm::vec3& value) const = 0;
            virtual void SetVec4(const std::string &name, const glm::vec4& value) const = 0;
    };

    class ShaderLibrary
    {
        public:
            void Add(const Ref<Shader>& shader);
            void Add(const std::string& name, const Ref<Shader>& shader);
            Ref<Shader> Load(const std::string& path);
            Ref<Shader> Load(const std::string& name, const std::string& path);

            Ref<Shader> Get(const std::string& name) const;

            bool Exists(const std::string& name) const;

        private:
            std::unordered_map<std::string, Ref<Shader>> shaders;
    };
}

#endif // SHADER_HPP
