#include "max_distance_filter.h"
#include "closest_polymesh_point.h"

#include <limits>
#include <vtkPolyData.h>
#include <vtkInformation.h>
#include <vtkKdTree.h>


vtkStandardNewMacro(MaxDistanceFilter);


MaxDistanceFilter::MaxDistanceFilter() {
	SetNumberOfInputPorts(2);
	SetNumberOfOutputPorts(0);
}


int MaxDistanceFilter::FillInputPortInformation(int port,
                                                vtkInformation *info) {
	if (port == 0) {
		vtkPolyDataAlgorithm::FillInputPortInformation(port, info);
	} else if (port == 1) {
		info->Set(vtkDataObject::DATA_TYPE_NAME(), "vtkPolyData");
	}
	return 1;
}


vtkTypeBool MaxDistanceFilter::RequestData(vtkInformation *request,
                                           vtkInformationVector **inputVector,
                                           vtkInformationVector *outputVector) {
	(void) request;
	(void) outputVector;
	vtkPolyData* input1 = vtkPolyData::GetData(inputVector[0]);
	vtkPolyData* input2 = vtkPolyData::GetData(inputVector[1]);
	vtkNew<vtkKdTree> tree1;
	tree1->BuildLocatorFromPoints(input1->GetPoints());
	vtkNew<vtkKdTree> tree2;
	tree2->BuildLocatorFromPoints(input2->GetPoints());
	vtkNew<vtkStaticCellLinks> links1;
	links1->BuildLinks(input1);
	vtkNew<vtkStaticCellLinks> links2;
	links2->BuildLinks(input2);
	MaxDist = 0;
	for (vtkIdType i = 0; i < input1->GetNumberOfPoints(); i++) {
		vtkIdType nCells = links1->GetNcells(i);
		if (nCells == 0) continue;
		double point[3];
		input1->GetPoint(i, point);
		double vec[3];
		double dist;
		closestPolyMeshPoint(input2, point, tree2, links2, vec, &dist);
		if (dist > MaxDist) {
			MaxDist = dist;
			MaxId = i;
			MaxInput = 0;
		}
	}
	for (vtkIdType i = 0; i < input2->GetNumberOfPoints(); i++) {
		vtkIdType nCells = links2->GetNcells(i);
		if (nCells == 0) continue;
		double point[3];
		input2->GetPoint(i, point);
		double vec[3];
		double dist;
		closestPolyMeshPoint(input1, point, tree1, links1, vec, &dist);
		if (dist > MaxDist) {
			MaxDist = dist;
			MaxId = i;
			MaxInput = 1;
		}
	}
	return true;
}
