#ifndef GPC_POLYGON_H
#define GPC_POLYGON_H

#include <Indoor/floorplan/v2/Floorplan.h>
#include "gpc.h"

class Polygon {

	struct GPCPolygon : gpc_polygon {
		GPCPolygon() {
//			contour = (gpc_vertex_list*) calloc(0, 1024);
//			contour->num_vertices = 0;
//			contour->vertex = (gpc_vertex*) calloc(0, 1024);
//			hole = (int*) calloc(0, 1024);
			num_contours = 0;
			contour = nullptr;
			hole = nullptr;
		}
		~GPCPolygon() {
			if (contour) {
				gpc_free_polygon(this);
				//free(contour->vertex); contour->vertex = nullptr;
			}
			free(contour); contour = nullptr;
			free(hole); hole = nullptr;

		}
		GPCPolygon& operator = (const GPCPolygon& o) = delete;
		GPCPolygon& operator = (GPCPolygon& o) {
			this->contour = o.contour;
			this->hole = o.hole;
			this->num_contours = o.num_contours;
			o.contour = nullptr;
			o.hole = nullptr;
			return *this;
		}
	};

private:

	GPCPolygon state;

public:

	void add(const Floorplan::Polygon2& poly) {
		GPCPolygon cur = toGPC(poly);
		//GPCPolygon out;
		gpc_polygon_clip(GPC_UNION, &state, &cur, &state);
		//state = out;
	}

	void remove(const Floorplan::Polygon2& poly) {
		GPCPolygon cur = toGPC(poly);
		//GPCPolygon out;
		gpc_polygon_clip(GPC_DIFF, &state, &cur, &state);
		//state = out;
	}

	std::vector<std::vector<Point3>> get(float z) {

		gpc_tristrip res;
		res.num_strips = 0;
		res.strip = nullptr;

		//res.strip = (gpc_vertex_list*) malloc(1024);
		gpc_polygon_to_tristrip(&state, &res);

		std::vector<std::vector<Point3>> trias;

		for (int i = 0; i < res.num_strips; ++i) {
			gpc_vertex_list lst = res.strip[i];
			std::vector<Point3> tria;
			for (int j = 0; j < lst.num_vertices; ++j) {
				gpc_vertex& vert = lst.vertex[j];
				Point3 p3(vert.x, vert.y, z);
				tria.push_back(p3);
			}
			trias.push_back(tria);
		}

		gpc_free_tristrip(&res);

		return std::move(trias);

	}

private:

	GPCPolygon toGPC(Floorplan::Polygon2 poly) {

		std::vector<gpc_vertex> verts;
		for (Point2 p2 : poly.points) {
			gpc_vertex vert; vert.x = p2.x; vert.y = p2.y;
			verts.push_back(vert);
		}

		GPCPolygon gpol;
		gpc_vertex_list list;
		list.num_vertices = verts.size();
		list.vertex = verts.data();
		gpc_add_contour(&gpol, &list, 0);

		return gpol;

	}

};

#endif // GPC_POLYGON_H
