#include "quad_patch_tesselator.h"
#include "mesh_processor.h"
#include "util.h"
#include "smoothing.h"
#include "curvature.h"
#include <QGenericMatrix>
#include <unordered_set>


static std::vector<std::vector<HalfedgeHandle>> findHoles(MyMesh &mesh) {
	std::vector<std::vector<HalfedgeHandle>> holes;
	std::set<HalfedgeHandle> ignore;
	for (HalfedgeHandle it : mesh.halfedges()) {
		if (mesh.is_boundary(it)
			&& ignore.find(it) == ignore.end()) {
			holes.emplace_back();
			holes.back().push_back(it);
			ignore.insert(it);
			for (HalfedgeHandle it2 : HalfedgeLoopRange<MyMesh>(mesh, it)) {
				holes.back().push_back(it2);
				ignore.insert(it2);
			}
		}
	}
	return holes;
}


MeshProcessor::MeshProcessor(const QString &path) {
	OpenMesh::IO::Options options;
	options.set(OpenMesh::IO::Options::VertexColor);
	if (!OpenMesh::IO::read_mesh(mesh, path.toUtf8().constData(), options)) {
		qWarning() << "Failed to read" << path;
		return;
	}
	mesh.update_normals();
	Courbures courb(mesh);
	courb.compute_KH();
    courb.set_K_colors();
	VertexHandle vh = mesh.vertex_handle(16);
	QuadPatch q = mesh.property(courb.vprop_quad, vh);
	patch = tesselate_quad_patch(q, mesh, vh);
	// mesh.holes = findHoles(mesh);
	// fillHoles();
	// smooth(mesh);
}


void fillHoleDumb(MyMesh &mesh, std::vector<HalfedgeHandle> &hole) {
	mesh.request_vertex_status();
	mesh.request_edge_status();
	mesh.request_face_status();

	Point center(0, 0, 0);
	size_t length = 0;
	for (HalfedgeHandle it : hole) {
		VertexHandle vert = mesh.to_vertex_handle(it);
		center += mesh.point(vert);
		length++;
	}
	center /= length;
	VertexHandle center_handle = mesh.new_vertex_dirty(center);

	for (HalfedgeHandle it : hole) {
		mesh.add_face(mesh.from_vertex_handle(it),
					  mesh.to_vertex_handle(it),
					  center_handle);
	}
}

void MeshProcessor::fillHoles() {
	for (auto hole : mesh.holes) {
		fillHoleDumb(mesh, hole);
	}
}