#ifndef GLPOINTS_H
#define GLPOINTS_H


#include <QOpenGLFunctions>
#include "GL.h"
#include "GLHelper.h"

#include <Indoor/geo/Point3.h>

class GLPoints : protected QOpenGLFunctions {

private:

	QOpenGLBuffer arrayBuf;
	QOpenGLBuffer indexBuf;

	std::vector<VertColor> vertices;
	std::vector<GLuint> indices;

	// use rectangles instead of GL_POINTS
	int mode = GL_TRIANGLES;
	bool initOnce = true;

public:

	/** ctor */
	GLPoints() : arrayBuf(QOpenGLBuffer::VertexBuffer), indexBuf(QOpenGLBuffer::IndexBuffer) {
		alloc();
	}

	/** dtor */
	~GLPoints() {
		destroy();
	}

	/** add a new face to this element */
	void addPoint(const QVector3D& pt, const QColor& color) {

		const QVector3D c(color.redF(), color.greenF(), color.blueF());

		float s = 10 / 100.0f;

		const VertColor vc1(pt + QVector3D(-s, 0, -s), c);
		const VertColor vc2(pt + QVector3D(+s, 0, -s), c);
		const VertColor vc3(pt + QVector3D(+s, 0, +s), c);
		const VertColor vc4(pt + QVector3D(-s, 0, +s), c);

		const int start = vertices.size();

		vertices.push_back(vc1);
		vertices.push_back(vc2);
		vertices.push_back(vc3);
		vertices.push_back(vc4);

		indices.push_back(start + 3);
		indices.push_back(start + 2);
		indices.push_back(start + 1);

		indices.push_back(start + 3);
		indices.push_back(start + 1);
		indices.push_back(start + 0);

	}


	void alloc() {
		if (!indexBuf.isCreated()) {indexBuf.create();}
		if (!arrayBuf.isCreated()) {arrayBuf.create();}
	}

	void destroy() {
		if (indexBuf.isCreated()) {indexBuf.destroy();}
		if (arrayBuf.isCreated()) {arrayBuf.destroy();}
	}

	/** build the underlying buffers */
	void build() {

		// Transfer vertex data to VBO 0
		arrayBuf.bind();
		arrayBuf.allocate(vertices.data(), vertices.size() * sizeof(vertices[0]));

		// Transfer index data to VBO 1
		indexBuf.bind();
		indexBuf.allocate(indices.data(), indices.size() * sizeof(indices[0]));

	}

	void initGL() {
		initializeOpenGLFunctions();
	}

	void rebuild() {
		build();
	}

	void clear() {
		indices.clear();
		vertices.clear();
	}

	void setMode(const int mode) {
		this->mode = mode;
	}

	/** render the element */
	void render(QOpenGLShaderProgram *program) {

		if (indices.empty()) {return;}

		// Tell OpenGL which VBOs to use
		arrayBuf.bind();
		indexBuf.bind();

		// vertices
		int vertLoc = program->attributeLocation("a_position");
		program->enableAttributeArray(vertLoc);
		program->setAttributeBuffer(vertLoc, GL_FLOAT, vertices[0].getVertOffset(), 3, sizeof(vertices[0]));

		// colors
		int colorLoc = program->attributeLocation("a_color");
		program->enableAttributeArray(colorLoc);
		program->setAttributeBuffer(colorLoc, GL_FLOAT, vertices[0].getColorOffset(), 3, sizeof(vertices[0]));

		// Draw cube geometry using indices from VBO 1
		glDrawElements(mode, indices.size(), GL_UNSIGNED_INT, 0);

	}


};

#endif // GLPOINTS_H
