/*=========================================================================
 *
 *  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 "itkImageFileReader.h"

#include "itkAttributeLabelObject.h"
#include "itkLabelImageToLabelMapFilter.h"
#include "itkTestingMacros.h"


int
itkAttributeLabelObjectAccessorsTest1(int argc, char * argv[])
{

  if (argc != 3)
  {
    std::cerr << "Missing parameters." << std::endl;
    std::cerr << "Usage: " << itkNameOfTestExecutableMacro(argv);
    std::cerr << " label input" << std::endl;
    return EXIT_FAILURE;
  }

  // declare the dimension used, and the type of the input image
  constexpr int dim{ 2 };
  using PType = unsigned char;
  using IType = itk::Image<PType, dim>;

  // The AttributeLabelObject class take 3 template parameters: the 2 ones
  // from the LabelObject class, and the type of the attribute associated
  // with each node. Here we have chosen a double. We then declare the
  // type of the LabelMap with the type of the label object.
  using LabelObjectType = itk::AttributeLabelObject<unsigned long, dim, double>;
  using LabelMapType = itk::LabelMap<LabelObjectType>;

  // We read the input image.
  using ReaderType = itk::ImageFileReader<IType>;
  auto reader = ReaderType::New();
  reader->SetFileName(argv[1]);

  auto reader2 = ReaderType::New();
  reader2->SetFileName(argv[2]);

  // And convert it to a LabelMap
  using I2LType = itk::LabelImageToLabelMapFilter<IType, LabelMapType>;
  auto i2l = I2LType::New();
  i2l->SetInput(reader->GetOutput());
  // The next step is made outside the pipeline model, so we call Update() now.
  i2l->Update();
  reader2->Update();

  IType * reader2Output = reader2->GetOutput();

  // Now we will valuate the attributes. The attribute will be the mean of the pixels
  // values in the 2nd image. The StatisticsLabelObject can give us that value, without
  // having to code that by hand - that's an example.

  const LabelMapType::Pointer labelMap = i2l->GetOutput();
  for (LabelMapType::Iterator it(labelMap); !it.IsAtEnd(); ++it)
  {
    // the label is there if we need it, but it can also be found at labelObject->GetLabel().
    // const PType & label = it->first;

    // the label object
    LabelObjectType * labelObject = it.GetLabelObject();

    ITK_EXERCISE_BASIC_OBJECT_METHODS(labelObject, AttributeLabelObject, LabelObject);


    // init the vars
    double        mean = 0;
    unsigned long size = 0;

    // the iterator for the indexes
    LabelObjectType::ConstIndexIterator it2(labelObject);
    while (!it2.IsAtEnd())
    {
      mean += reader2Output->GetPixel(it2.GetIndex());
      size++;
      ++it2;
    }

    if (size)
    {
      mean /= size;
    }

    labelObject->SetAttribute(mean);
    // make sure that we get the same value
    ITK_TEST_SET_GET_VALUE(mean, labelObject->GetAttribute());
    // make sure that the accessor provide the same values than the GetAttribute() method
    itk::Functor::AttributeLabelObjectAccessor<LabelObjectType> accessor;
    ITK_TEST_SET_GET_VALUE(accessor(labelObject), labelObject->GetAttribute());
  }

  return EXIT_SUCCESS;
}
