#include <pch.hpp>

#include <core.hpp>
#include <open_engine/renderer/shader.hpp>
#include <open_engine/renderer/renderer_api.hpp>
#include <open_engine/renderer/renderer.hpp>
#include <opengl/opengl_shader.hpp>
#include <logging.hpp>

namespace OpenEngine {
    Ref<Shader> Shader::Create(const std::string& shader_path)
    {
        OE_PROFILE_FUNCTION();

        switch (Renderer::GetAPI())
        {
            case RendererAPI::API::None : OE_CORE_ASSERT(false, "No render API selected!"); return nullptr;
            case RendererAPI::API::OpenGL: return CreateRef<OpenGLShader>(shader_path);  
        }

        OE_CORE_ASSERT(false, "Unknown RendererAPI!");
        return nullptr;
    };

    Ref<Shader> Shader::Create(const std::string& name, const std::string& vertex_src, const std::string& frament_src)
    {
        OE_PROFILE_FUNCTION();

        switch (Renderer::GetAPI())
        {
            case RendererAPI::API::None : OE_CORE_ASSERT(false, "No render API selected!"); return nullptr;
            case RendererAPI::API::OpenGL: return CreateRef<OpenGLShader>(name, vertex_src, frament_src);  
        }

        OE_CORE_ASSERT(false, "Unknown RendererAPI!");
        return nullptr;
    };

    void ShaderLibrary::Add(const Ref<Shader>& shader)
    {
        OE_PROFILE_FUNCTION();

        auto shader_name = shader->GetName();
        Add(shader_name, shader);
    }

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

        if (Exists(name))
            OE_CORE_ERROR("Shader with this name already exists: ", name);

        shaders[name] = shader;
    }

    Ref<Shader> ShaderLibrary::Load(const std::string& path)
    {
        OE_PROFILE_FUNCTION();

        auto shader = Shader::Create(path);
        Add(shader);

        return shader;
    }

    Ref<Shader> ShaderLibrary::Load(const std::string& name, const std::string& path)
    {
        OE_PROFILE_FUNCTION();

        auto shader = Shader::Create(path);
        Add(name, shader);

        return shader;
    }

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

        if (!Exists(name))
            OE_CORE_ERROR("Shader with this name doesn't exists: ", name);
        return shaders.find(name)->second;
    }

    bool ShaderLibrary::Exists(const std::string& name) const
    {
        return shaders.find(name) != shaders.end();
    }
}
