//
// Created by sfd on 25-4-21.
//

#ifndef SHADER_H
#define SHADER_H
#include <string>
#include <unordered_map>
#include <Hazel/Core/Core.h>

#include "glm/fwd.hpp"
#include "glm/detail/func_packing_simd.inl"


namespace Hazel
{
    class HAZEL_API Shader
    {
    public:
        virtual ~Shader() = default;

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

        virtual void SetFloat(const std::string& name, float value) = 0;
        virtual void SetFloat3(const std::string& name, const glm::vec3& value) = 0;
        virtual void SetFloat4(const std::string& name, const glm::vec4& value) = 0;
        virtual void SetMat3(const std::string& name, const glm::mat3& value) = 0;
        virtual void SetMat4(const std::string& name, const glm::mat4& value) = 0;
        virtual void SetInt(const std::string& name, int value) = 0;
        virtual void SetIntv(const std::string& name, int* values, uint32_t count) = 0;

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

        static Ref<Shader> Create(const std::string& name, const std::string& vertexSrc, const std::string& fragmentSrc);
        static Ref<Shader> Create(const std::string& filepath);
    private:
        uint32_t m_RendererID;
    };

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

        Ref<Shader> Load(const std::string& filepath);                              // example: texture.glsl
        Ref<Shader> Load(const std::string& name, const std::string& filepath);

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

        bool Exists(const std::string& name) const;
    private:
        std::unordered_map<std::string, Ref<Shader>> m_Shaders;
    };

}


#endif //SHADER_H
