#ifndef STAIRS_H
#define STAIRS_H


#include <Indoor/floorplan/v2/Floorplan.h>
#include "../gl/GLHelper.h"
#include "../gl/GLTriangles.h"
#include "../Renderable.h"


class Stairs : public Renderable {

private:

	Floorplan::Floor* floor;

	GLTriangles<VertNormTex> parts;

public:

	/** ctor */
	Stairs(Floorplan::Floor* floor) : floor(floor) {
		;
	}


	void initGL() override {

		build();
//		parts.setDiffuse(":/res/gl/tex/granite1.jpg");
//		parts.setNormalMap(":/res/gl/tex/granite1_normal.jpg");
		parts.setDiffuse(":/res/gl/tex/floor4.jpg");
		parts.setNormalMap(":/res/gl/tex/floor4_normal.jpg");
		parts.build();

		loadShader(":/res/gl/vertex1.glsl", ":/res/gl/fragmentTex.glsl");
		program.setUniformValue("texDiffuse", 0);
		program.setUniformValue("texNormalMap", 1);

	}

	/** render the floor */
	void _render(const RenderParams& params) override {
		(void) params;
		parts.render(&program);
	}



private:

	void build() {

		for (Floorplan::Stair* stair : floor->stairs) {

			if (dynamic_cast<Floorplan::Stair*>(stair)) {
				Floorplan::StairFreeform* freeform = dynamic_cast<Floorplan::StairFreeform*>(stair);
				add(Floorplan::getQuads(freeform->getParts(), floor));
			}

		}

	}

	void add(const std::vector<Floorplan::Quad3>& quads) {

		for (const Floorplan::Quad3& quad : quads) {

			//void addQuad(quad);

			stepify(quad);

		}

	}

	void stepify(const Floorplan::Quad3& quad) {

		const float len = (quad.p4 - quad.p1).length();
		const float stepLen = 0.3;
		const int steps = std::round(len / stepLen);

		for (int i = 0; i < steps; ++i) {
			const float per1 = (float) (i+0) / (float) steps;
			const float per2 = (float) (i+1) / (float) steps;

			const Point3 p1 = quad.p1 + (quad.p4 - quad.p1) * per1;
			const Point3 p2 = quad.p2 + (quad.p3 - quad.p2) * per1;
			const Point3 p5 = quad.p2 + (quad.p3 - quad.p2) * per2;
			const Point3 p6 = quad.p1 + (quad.p4 - quad.p1) * per2;
			Point3 p3 = p5; p3.z = p2.z;
			Point3 p4 = p6; p4.z = p1.z;


			addQuad(Floorplan::Quad3(p1, p2, p3, p4));
			addQuad(Floorplan::Quad3(p3, p4, p6, p5));

		}

	}

	void addQuad(const Floorplan::Quad3& quad) {

		const QVector3D vert1(quad.p1.x, quad.p1.z, quad.p1.y);
		const QVector3D vert2(quad.p2.x, quad.p2.z, quad.p2.y);
		const QVector3D vert3(quad.p3.x, quad.p3.z, quad.p3.y);
		const QVector3D vert4(quad.p4.x, quad.p4.z, quad.p4.y);

		const QVector3D n1 = GLHelper::getNormal(vert1, vert2, vert3);
		const QVector3D n2 = -n1;

//		const float o =

//		const QVector2D tex1(quad.p1.length(), quad.p1.y);
//		const QVector2D tex2(quad.p2.x, quad.p2.y+quad.p2.z);
//		const QVector2D tex3(quad.p3.x, quad.p3.y+quad.p3.z);
//		const QVector2D tex4(quad.p4.x, quad.p4.y+quad.p4.z);

		const float h = quad.p4.getDistance(quad.p1);
		const float l = quad.p1.getDistance(quad.p2);
		const float o = quad.p1.length();
		const float s = 1.1;	// 0.5;

		const QVector2D tex1(o+0, h);		// start texturing at the ceiling so above-door-sections and walls have the same textre
		const QVector2D tex2(o+l, h);
		const QVector2D tex3(o+l, 0);
		const QVector2D tex4(o+0, 0);

//		const VertNormTex vnt1(vert1, n1, tex1*s);
//		const VertNormTex vnt2(vert2, n1, tex2*s);
//		const VertNormTex vnt3(vert3, n1, tex3*s);
//		const VertNormTex vnt4(vert4, n1, tex4*s);

		{
			const VertNormTex vnt1(vert1, n1, tex1*s);
			const VertNormTex vnt2(vert2, n1, tex2*s);
			const VertNormTex vnt3(vert3, n1, tex3*s);
			const VertNormTex vnt4(vert4, n1, tex4*s);
			parts.addQuadCCW(vnt1, vnt2, vnt3, vnt4);
		} {
			const VertNormTex vnt1(vert1, n2, tex1*s);
			const VertNormTex vnt2(vert2, n2, tex2*s);
			const VertNormTex vnt3(vert3, n2, tex3*s);
			const VertNormTex vnt4(vert4, n2, tex4*s);
			parts.addQuadCW(vnt1, vnt2, vnt3, vnt4);
		}

	}


};


#endif // STAIRS_H
