#pragma once

#include <vector>
#include <map>

#include "Mesh.h"
#include "Density.h"
#include "ProgressMonitor.h"

struct CompareVec3 {
	bool operator()(const glm::vec3 &lhs, const glm::vec3 &rhs) {
		static const float epsilon = 1e-5;
		if (lhs.x < rhs.x - epsilon)
			return true;
		else if (lhs.x > rhs.x + epsilon)
			return false;
		else {
			if (lhs.y < rhs.y - epsilon)
				return true;
			else if (lhs.y > rhs.y + epsilon)
				return false;
			else {
				if (lhs.z < rhs.z - epsilon)
					return true;
				else if (lhs.z > rhs.z + epsilon)
					return false;
				else {
					return false;
				}

			}
		}
	}
};

class Polygonizer {
	Density &density;
	float isolevel;

	std::vector<bool> isocell;
	size_t isocellVersion;
	float isocellIsolevel;

	void polygonize(const glm::vec3 &lower, const glm::vec3 &upper,
			float isolevel);

	void calculateLayer(std::vector<float> &layer, float resolution, size_t nSamples, float z);

public:
	Mesh mesh;
	std::map<glm::vec3, int, CompareVec3> vertexLookup;


	Polygonizer(Density &density, float isolevel);
	void setIsoLevel(float isolevel);

	void updateIsocell();

	void polygonize(float resolution, ProgressMonitor &progress);
};
