/*=========================================================================
 *
 *  Copyright NumFOCUS
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *         https://www.apache.org/licenses/LICENSE-2.0.txt
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *
 *=========================================================================*/

#include <iostream>

#include "itkInterpolateImageFilter.h"

int
itkInterpolateImageFilterTest(int, char *[])
{
  enum
  {
    ImageDimension = 2
  };
  using InputPixelType = unsigned long;
  using OutputPixelType = unsigned long;
  using InputImageType = itk::Image<InputPixelType, ImageDimension>;
  using OutputImageType = itk::Image<OutputPixelType, ImageDimension>;

  // fill images
  using SizeType = InputImageType::SizeType;
  auto size = SizeType::Filled(5);

  auto image1 = InputImageType::New();
  image1->SetRegions(size);
  image1->Allocate();
  image1->FillBuffer(100);

  auto image2 = InputImageType::New();
  image2->SetRegions(size);
  image2->Allocate();


  itk::ImageRegionIteratorWithIndex<InputImageType> inIter2(image2, image2->GetBufferedRegion());

  unsigned long temp = 0;
  while (!inIter2.IsAtEnd())
  {
    inIter2.Set(temp);
    temp += 2;
    ++inIter2;
  }

  using FilterType = itk::InterpolateImageFilter<InputImageType, OutputImageType>;
  auto filter = FilterType::New();

  filter->SetInput1(image1);
  filter->SetInput2(image2);
  filter->Print(std::cout);

  try
  {
    filter->Update();
  }
  catch (const itk::ExceptionObject & err)
  {
    std::cout << "Caught unexpected exception: " << err << std::endl;
    std::cout << "Test failed. " << std::endl;
    return EXIT_FAILURE;
  }

  // walk the output and check the results
  itk::ImageRegionIteratorWithIndex<InputImageType> inIter1(image1, image1->GetBufferedRegion());
  inIter2.GoToBegin();

  itk::ImageRegionIteratorWithIndex<OutputImageType> outIter(filter->GetOutput(),
                                                             filter->GetOutput()->GetBufferedRegion());

  temp = 50;
  while (!inIter1.IsAtEnd())
  {

    std::cout << ' ' << inIter1.Get() << ' ' << inIter2.Get() << ' ' << outIter.Get() << std::endl;

    if (outIter.Get() != temp)
    {
      std::cout << "Expected output " << temp << " got " << outIter.Get() << " instead. " << std::endl;
      std::cout << "Test failed. " << std::endl;
      return EXIT_FAILURE;
    }

    ++temp;
    ++inIter1;
    ++inIter2;
    ++outIter;
  }

  // exercise other methods
  filter->GetInput1();
  filter->GetInput2();
  filter->GetInterpolator();
  filter->SetDistance(0.2);
  filter->GetDistance();

  // set the interpolator to be null
  filter->SetInterpolator(nullptr);
  bool pass = false;

  try
  {
    filter->Update();
  }
  catch (const itk::ExceptionObject & err)
  {
    std::cout << "Caught expected exception: " << err << std::endl;
    pass = true;
  }

  if (!pass)
  {
    std::cout << "Test failed." << std::endl;
    return EXIT_FAILURE;
  }

  std::cout << "Test passed." << std::endl;
  return EXIT_SUCCESS;
}
