#ifndef VAO_INCLUDED
#define VAO_INCLUDED

#include <gfx/vbo.hpp>
#include <gfx/ebo.hpp>
#include <osi/opengl.hpp>
#include <utils/assumptions.hpp>

#include <memory>

using VBO_ptr = std::shared_ptr<VBO>;
using EBO_ptr = std::shared_ptr<EBO>;

class VAO
{
    unsigned int ID;

    std::size_t vertices_size;
    std::size_t normals_size;
    std::size_t indices_size;
    std::size_t texture_coordinates_size;

    VBO_ptr _VBO_vertex = nullptr;
    VBO_ptr _VBO_normal = nullptr;
    VBO_ptr _VBO_tex_coord = nullptr;
    EBO_ptr _EBO = nullptr;

public:
    VAO();
    ~VAO();
    void bind() const;
    void unbind() const;
    void deleteArray();

    void linkVBO(GLuint vbo_id, unsigned int layout_loc, GLint element_size);

    void bindVertices(std::vector<float> const &_vertices);
    void bindNormals(std::vector<float> const &_normals);
    void bindIndices(std::vector<unsigned int> const &_indices);
    void bindTextureCoordinates(std::vector<float> const &texture_coordinates);

    void bindBuffers(std::vector<float> const &vertices, 
                     std::vector<float> const &normals,
                     std::vector<unsigned int> const &indices,
                     std::vector<float> const &texture_coordinates);

    const std::size_t getVerticesSize() const { return vertices_size; }
    void setVerticesSize(std::vector<float> const &vertices) { vertices_size = vertices.size(); }

    const std::size_t getNormalsSize() const { return normals_size; }
    void setNormalsSize(std::vector<float> const &normals) { normals_size = normals.size(); }

    const std::size_t getIndicesSize() const { return indices_size; }
    void setIndicesSize(std::vector<unsigned int> const &indices) { indices_size = indices.size(); }

    const std::size_t getTextureCoordinatesSize() const { return texture_coordinates_size; }
    void setTextureCoordinatesSize(std::vector<float> const &texture_coordinates) { texture_coordinates_size = texture_coordinates.size(); }
};

#endif