#ifndef GLLINES_H
#define GLLINES_H

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

#include <Indoor/geo/Point3.h>

class GLLines : protected QOpenGLFunctions {

private:

	QOpenGLBuffer arrayBuf;
	QOpenGLBuffer indexBuf;

	std::vector<Vert> vertices;
	std::vector<GLushort> indices;

	int mode = GL_LINES;

public:

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

	/** dtor */
	~GLLines() {
		arrayBuf.destroy();
		indexBuf.destroy();
	}

	/** add a new face to this element */
	void addLine(const QVector3D& p1, const QVector3D& p2) {

		// add vertices (remove duplicates!)
		const int i1 = addOnce(p1);
		const int i2 = addOnce(p2);

		// add indices
		indices.push_back(i1);
		indices.push_back(i2);

	}

	void addVertex(const QVector3D& p1) {
		const int i1 = addOnce(p1);
		indices.push_back(i1);
	}


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

		initializeOpenGLFunctions();

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

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

	}

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

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

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

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

		// 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]));

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

	}

private:

	/** to conserve memory, avoid duplicate VNTs! */
	int addOnce(const Vert& vnt) {

		const auto it = std::find(vertices.begin(), vertices.end(), vnt);

		if (it == vertices.end()) {
			const int idx = vertices.size();
			vertices.push_back(vnt);
			return idx;
		} else {
			const int idx = it - vertices.begin();
			return idx;
		}

	}




};

#endif // GLLINES_H
