#ifndef MODEL3D_HPP
#define MODEL3D_HPP

#include "open_engine/core/uuid.hpp"
#include "open_engine/renderer/vertex_array.hpp"
#include <cstddef>
#include <cstdint>
#include <glm/glm.hpp>
#include <vector>

namespace OpenEngine {

    struct Material
    {
        glm::vec4 albedo = { 1.0f, 0.0f, 0.8f, 1.0f };
        float roughness = 1.0f;
        float metallic = 1.0f;
        float ambient_strength = 1.0f;
        float specular_strength = 1.0f;
        std::string name = "un-named material";
    };

    struct MeshVertex
    {
        glm::vec3 position;
        glm::vec3 normal;
        glm::vec2 text_coords;
    };

    struct Mesh
    {
        UUID uuid;

        Material material;

        Ref<VertexArray> vertex_array;
        Ref<VertexBuffer> vertex_buffer;
        Ref<IndexBuffer> index_buffer;

        // TODO: Make them a ptr or something
        std::vector<MeshVertex> vertices;
        std::vector<uint32_t> indices;
    };

    // TODO: Model3D.Instanciate();
    // Or Model3D.GetVertices() {return iterateaccessorwithindex bla bla bla}
    // What data should Model3D hold in the end if it is not a renderable object?
    class Model3D
    {
        public:
            virtual ~Model3D() = default;

            static Ref<Model3D> Create(const char* path);

            virtual const Mesh& GetMesh(int index) const = 0;
            virtual const std::vector<Mesh>& GetMeshes() const = 0;

            virtual size_t GetMeshCount() const = 0;

            virtual std::vector<Mesh>::iterator begin() = 0;
            virtual std::vector<Mesh>::iterator end() = 0;

            virtual std::vector<Mesh>::const_iterator begin() const = 0;
            virtual std::vector<Mesh>::const_iterator end() const = 0;
    };

}

#endif // MODEL3D_HPP
