/*=========================================================================
 *
 *  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.
 *
 *=========================================================================*/
#ifndef itkAnchorUtilities_hxx
#define itkAnchorUtilities_hxx

#include "itkImageRegionConstIteratorWithIndex.h"
#include "itkImageRegionConstIterator.h"
#include "itkNeighborhoodAlgorithm.h"

namespace itk
{
/**
 * AnchorUtilities
 * functionality in common for anchor openings/closings and
 * erosions/dilation
 *
 **/
template <typename TImage, typename TBres, typename TAnchor, typename TLine>
void
DoAnchorFace(const TImage *                            input,
             TImage *                                  output,
             typename TImage::PixelType                border,
             TLine                                     line,
             TAnchor &                                 AnchorLine,
             const typename TBres::OffsetArray         LineOffsets,
             std::vector<typename TImage::PixelType> & inbuffer,
             std::vector<typename TImage::PixelType> & outbuffer,
             const typename TImage::RegionType         AllImage,
             const typename TImage::RegionType         face)
{
  // iterate over the face

  // we can't use an iterator with a region outside the image. All we need here
  // is to
  // iterate over all the indexes of the face, without accessing the content of
  // the image.
  // I can't find any cleaner way, so we use a dumb image, not even allocated,
  // to iterate
  // over all the indexes inside the region.
  //
  // using ItType = ImageRegionConstIteratorWithIndex<TImage>;
  // ItType it(input, face);

  auto dumbImg = TImage::New();
  dumbImg->SetRegions(face);

  TLine NormLine = line;
  NormLine.Normalize();
  // set a generous tolerance
  float tol = 1.0 / LineOffsets.size();
  for (unsigned int it = 0; it < face.GetNumberOfPixels(); ++it)
  {
    typename TImage::IndexType Ind = dumbImg->ComputeIndex(it);
    unsigned int               start, end;
    if (FillLineBuffer<TImage, TBres, TLine>(input, Ind, NormLine, tol, LineOffsets, AllImage, inbuffer, start, end))
    {
      const unsigned int len = end - start + 1;
      // compat
      inbuffer[0] = border;
      inbuffer[len + 1] = border;

      AnchorLine.DoLine(outbuffer, inbuffer, len + 2); // compat
      CopyLineToImage<TImage, TBres>(output, Ind, LineOffsets, outbuffer, start, end);
    }
  }
}
} // namespace itk

#endif
