#pragma once

#include "blitz/Defines.h"

#include <vector>

namespace blitz {
namespace GL {

struct VertexAttribPointer {
	unsigned int m_Index;
	unsigned int m_Size;
	unsigned int m_Offset;
};

class VertexBuffer {
  private:
	unsigned int m_ID, m_DataStride;
	std::vector<VertexAttribPointer> m_VertexAttribs;

  public:
	VertexBuffer(VertexBuffer&& other) {
		m_VertexAttribs = std::move(other.m_VertexAttribs);
		m_ID = other.m_ID;
		m_DataStride = other.m_DataStride;
		other.m_ID = 0;
		other.m_DataStride = 0;
	}

	VertexBuffer(const std::vector<float>& data, unsigned int stride);
	~VertexBuffer();

	void Bind() const;
	void Unbind() const;
	void AddVertexAttribPointer(unsigned int index, unsigned int coordinateSize, unsigned int offset);
	void BindVertexAttribs() const;

	REMOVE_COPY(VertexBuffer);
};

class VertexArray {
  private:
	unsigned int m_ID, m_VertexCount;
	std::vector<VertexBuffer> m_VertexBuffers;	// use to destroy vbos when become unused
  public:
	VertexArray(VertexArray&& other) {
		m_ID = other.m_ID;
		m_VertexCount = other.m_VertexCount;
		m_VertexBuffers = std::move(other.m_VertexBuffers);
		other.m_VertexCount = 0;
		other.m_ID = 0;
	}

	VertexArray(unsigned int vertexCount);
	~VertexArray();

	unsigned int GetVertexCount() const {
		return m_VertexCount;
	}

	void BindVertexBuffer(VertexBuffer& vbo);
	void Bind() const;
	void Unbind() const;

	REMOVE_COPY(VertexArray);
};

}  // namespace GL
}  // namespace blitz
