#ifndef RENDERABLE_H
#define RENDERABLE_H

#include <QOpenGLShaderProgram>
#include "RenderParams.h"

class Renderable {

protected:

	QOpenGLShaderProgram program;

public:

	/** dtor */
	virtual ~Renderable() {;}

	/** get the renderable's shader */
	QOpenGLShaderProgram& getProgram() {return program;}

	/** render the renderable */
	void render(const RenderParams& params) {
		program.bind();
		_render(params);
	}

	struct ModelMatrix {
		QVector3D pos = QVector3D(0,0,0);
		QVector3D rot = QVector3D(0,0,0);
		QVector3D scale = QVector3D(1,1,1);
		QMatrix4x4 mat;
		ModelMatrix() {mat.setToIdentity();}
		void update() {
			const QVector3D _rot = rot.normalized();
			const float rotDeg = rot.length();
			mat.setToIdentity();
			mat.scale(scale.x(), scale.y(), scale.z());
			mat.translate(pos.x(), pos.y(), pos.z());
			mat.rotate(rotDeg, _rot.x(), _rot.y(), _rot.z());
		}
	} modelMatrix;

	void setPosition(QVector3D vec) {
		modelMatrix.pos = vec * 0.99;
		modelMatrix.update();
	}

	void setPosition(const float x, const float y, const float z) {
		setPosition(QVector3D(x,z,y));
	}

	/** in degrees! */
	void setRotation(const float x, const float y, const float z) {
		modelMatrix.rot = QVector3D(x,z,y);
		modelMatrix.update();
	}

	virtual void setOutlineOnly(const bool outline) { (void) outline; }

	virtual void setTransparent(const bool transparent) { (void) transparent; }

	virtual void initGL() = 0;

	virtual void _render(const RenderParams& params) = 0;

protected:

	/** helper method to build the shader */
	void loadShader(const QString& vertex, const QString& fragment) {
		program.removeAllShaders();
		if (!program.addShaderFromSourceFile(QOpenGLShader::Vertex, vertex)) {throw "1";}
		if (!program.addShaderFromSourceFile(QOpenGLShader::Fragment, fragment)) {throw "2";}
		if (!program.link()) {throw "3";}
		if (!program.bind()) {throw "4";}
	}

};

#endif // RENDERABLE_H
