#include "Interpolator.h"
#include <vtkSmartPointer.h>
#include <vtkGaussianKernel.h>
#include <vtkPointInterpolator.h>
#include <vtkPolyData.h>
#include <vtkPointData.h>
#include <vtkDoubleArray.h>
#include <vtkPolyDataWriter.h>

Interpolator::Interpolator()
{


}


void Interpolator::setOldPoints(std::vector<std::vector<double>> op)
{
    old_points = op;
}

void Interpolator::setNewPoints(std::vector<std::vector<double>> np)
{
    new_points = np;
}

void Interpolator::setOldData(std::vector<double> od)
{
    old_data = od;
}


std::vector<double> Interpolator::getInterpolatedData()
{

    vtkSmartPointer<vtkGaussianKernel> interpolation_kernel =
        vtkSmartPointer<vtkGaussianKernel>::New();
    interpolation_kernel->SetKernelFootprintToNClosest();
    interpolation_kernel->SetNumberOfPoints(8);

    // old geometry
    vtkSmartPointer<vtkPoints> old_vtkpoints =
        vtkSmartPointer<vtkPoints>::New();

    vtkSmartPointer<vtkDataArray> old_vtkdata = vtkSmartPointer<vtkDoubleArray>::New();
    old_vtkdata->SetNumberOfComponents(1);
    old_vtkdata->SetName("field");


    for (int i = 0; i < old_points.size(); i++)
    {
        double p[3];
        p[0] = old_points[i][0];
        p[1] = old_points[i][1];
        p[2] = old_points[i][2];
        old_vtkpoints->InsertNextPoint(p);
        old_vtkdata->InsertNextTuple1(old_data[i]);
    }

    vtkSmartPointer<vtkPolyData> old_geometry = vtkSmartPointer<vtkPolyData>::New();

    old_geometry->SetPoints(old_vtkpoints);
    old_geometry->GetPointData()->SetScalars(old_vtkdata);
    old_geometry->GetPointData()->SetActiveScalars("field");

    vtkSmartPointer<vtkPolyDataWriter> polywriter0 =
        vtkSmartPointer<vtkPolyDataWriter>::New();

    // new geometry
    vtkSmartPointer<vtkPoints> new_vtkpoints =
        vtkSmartPointer<vtkPoints>::New();

    for (int i = 0; i < new_points.size(); i++)
    {
        double p[3];
        p[0] = new_points[i][0];
        p[1] = new_points[i][1];
        p[2] = new_points[i][2];
        new_vtkpoints->InsertNextPoint(p);
    }

    vtkSmartPointer<vtkPolyData> new_geometry = vtkSmartPointer<vtkPolyData>::New();

    new_geometry->SetPoints(new_vtkpoints);


    vtkSmartPointer<vtkPointInterpolator> interpolator =
        vtkSmartPointer<vtkPointInterpolator>::New();
    interpolator->SetSourceData(old_geometry);
    interpolator->SetInputData(new_geometry);
    interpolator->SetKernel(interpolation_kernel);
    interpolator->Update();

    vtkSmartPointer<vtkPolyData> updatedgeom = vtkPolyData::SafeDownCast(interpolator->GetOutput());

    vtkSmartPointer<vtkPolyDataWriter> polywriter1 =
        vtkSmartPointer<vtkPolyDataWriter>::New();

    std::vector<double> return_vec;
    std::string name;
    vtkSmartPointer<vtkDataArray> data = updatedgeom->GetPointData()->GetArray(0);

    for (int i = 0; i < updatedgeom->GetNumberOfPoints(); i++)
    {
        return_vec.push_back(data->GetTuple1(i));
    }

    return return_vec;
}