
#include <Spectre/Graphics/Texture.h>
#include <Spectre/Graphics/OpenGL.h>
#include <Spectre/Graphics/Renderable.h>
#include <Spectre/Graphics/DefaultRenderer2D.h>

DefaultRenderer2D::DefaultRenderer2D() 
{
	m_shader.create();
	if (!m_shader.loadFromFile("assets/shaders/standard.shader.glsl")) {
		std::cout << "Failed to load shader: " << m_shader.getLastError() << std::endl;
	}

	if (!m_shader.link()) {
		std::cout << "Failed to link shader: " << m_shader.getLastError() << std::endl;
	}
}

void DefaultRenderer2D::submit(const Renderable2D& renderable)
{
	m_queue.push_back(&renderable);
}

void DefaultRenderer2D::render()
{
	Matrix4f viewMatrix;

	if (m_camera) {
		viewMatrix = m_camera->getViewMatrix();
	} else {
		viewMatrix = Matrix4f::Identity;
	}

	m_shader.enable();

	glEnableVertexAttribArray(VertexAttribPosition);
	glEnableVertexAttribArray(VertexAttribColor0);
	glEnableVertexAttribArray(VertexAttribTexCoord0);

	for(size_t i = 0; i < m_queue.size(); i++) {

		const Renderable2D* obj = m_queue[i];
		const std::vector<Vertex2D> vertices = obj->getVertices();
		const std::vector<unsigned short> indices = obj->getIndices();
		unsigned char *data = (unsigned char*) &vertices[0];
		const Texture *tex = obj->getTexture();

		Matrix4f modelViewMatrix = viewMatrix * obj->getTransform().getMatrix();
		m_shader.setMVPMatrix(modelViewMatrix);

		glVertexAttribPointer(VertexAttribPosition, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), data + 0);
		glVertexAttribPointer(VertexAttribColor0, 3, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), data + 8);
		glVertexAttribPointer(VertexAttribTexCoord0, 2, GL_FLOAT, GL_FALSE, sizeof(Vertex2D), data + 20);

		if (tex) {
			tex->enable();
		}

		glDrawElements(GL_TRIANGLES, indices.size(), GL_UNSIGNED_SHORT, &indices[0]);

		if (tex) {
			tex->disable();
		}
	}

	glDisableVertexAttribArray(VertexAttribPosition);
	glDisableVertexAttribArray(VertexAttribColor0);
	glDisableVertexAttribArray(VertexAttribTexCoord0);

	m_shader.disable();
	m_queue.clear();
}