#include "angles_filter.h"
#include "aspect_ratio_filter.h"

#include <vtkCellData.h>
#include <vtkUnstructuredGrid.h>
#include <vtkCamera.h>
#include <vtkNamedColors.h>
#include <vtkVolumeProperty.h>
#include <vtkRenderWindow.h>
#include <vtkRenderWindowInteractor.h>
#include <vtkRenderer.h>
#include <vtkVolumeMapper.h>
#include <vtkVolume.h>
#include <vtkOpenGLProjectedTetrahedraMapper.h>
#include <vtkUnstructuredGridReader.h>
#include <vtkPiecewiseFunction.h>

#include <array>
#include <vector>
#include <algorithm>


// template <typename T>
// T average(const std::vector<T> &data) {
// 	T avg = 0;
// 	for (const T &t : data) {
// 		avg += t;
// 	}
// 	return avg / data.size();
// }


// template <typename T>
// T standard_deviation(const std::vector<T> &data) {
// 	T avg = average(data);
// 	T stddev = 0;
// 	for (const T &t : data) {
// 		stddev += (t - avg) * (t - avg);
// 	}
// 	return std::sqrt(stddev / data.size());
// }


int main(int argc, char **argv) {
	if (argc != 2) {
		std::cerr << "Usage: " << argv[0] << " FILE.vtk" << std::endl;
		return EXIT_FAILURE;
	}

	/* Reader */
	vtkNew<vtkUnstructuredGridReader> reader;
	reader->SetFileName(argv[1]);


	/* Angle filter */
	vtkNew<AnglesFilter> anglesFilter;
	anglesFilter->SetInputConnection(reader->GetOutputPort());

	/* Display angles in console. */
	anglesFilter->Update();
	vtkUnstructuredGrid *grid = anglesFilter->GetOutput();
	auto *angles = grid->GetCellData()->GetArray("angles");
	for (ssize_t i = 0; i < angles->GetNumberOfTuples(); i++) {
		std::cout << "cell " << i << ": ";
		for (ssize_t j = 0; j < angles->GetNumberOfComponents(); j++) {
			std::cout << angles->GetTuple(i)[j] << ", ";
		}
		std::cout << "\b\b \n";
	}

	/* Aspect ratio */
	vtkNew<AspectRatioFilter> aspectRatioFilter;
	aspectRatioFilter->SetInputConnection(anglesFilter->GetOutputPort());

	/* Display aspect ratios in console. */
	aspectRatioFilter->Update();
	grid = aspectRatioFilter->GetOutput();
	auto *aspectRatios = grid->GetCellData()->GetArray("aspect_ratio");
	for (ssize_t i = 0; i < aspectRatios->GetNumberOfTuples(); i++) {
		std::cout << "cell " << i << ": "
				  << aspectRatios->GetTuple1(i) << "\n";
	}

	/* Volume rendering properties */
	vtkNew<vtkOpenGLProjectedTetrahedraMapper> volumeMapper;
	volumeMapper->SetInputConnection(aspectRatioFilter->GetOutputPort());
	vtkNew<vtkVolume> volume;
	volume->SetMapper(volumeMapper);
	vtkNew<vtkPiecewiseFunction> transferFunction;
	transferFunction->AddPoint(-1, 0);
	transferFunction->AddPoint(1, 1);
	volume->GetProperty()->SetScalarOpacity(transferFunction);
	volume->GetProperty()->SetColor(transferFunction);

	/* Renderer */
	vtkNew<vtkNamedColors> colors;
	std::array<unsigned char, 4> bkg{{26, 51, 102, 255}};
	colors->SetColor("BkgColor", bkg.data());
	vtkNew<vtkRenderer> renderer;
	renderer->AddVolume(volume);
	renderer->SetBackground(colors->GetColor3d("BkgColor").GetData());
	renderer->ResetCamera();
	renderer->GetActiveCamera()->Zoom(1.5);
	vtkNew<vtkRenderWindow> renderWindow;
	renderWindow->SetSize(300, 300);
	renderWindow->AddRenderer(renderer);
	renderWindow->SetWindowName("PFE");
	vtkNew<vtkRenderWindowInteractor> renderWindowInteractor;
	renderWindowInteractor->SetRenderWindow(renderWindow);
	renderWindow->Render();
	renderWindowInteractor->Start();

	return EXIT_SUCCESS;
}
