/*=========================================================================
 *
 *  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
 *
 *         http://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 sitkPasteImageFilter_h
#define sitkPasteImageFilter_h

/*
 * WARNING: DO NOT EDIT THIS FILE!
 * THIS FILE IS AUTOMATICALLY GENERATED BY THE SIMPLEITK BUILD PROCESS.
 * Please look at sitkImageFilterTemplate.h.in to make changes.
 */

#include <memory>

#include "sitkBasicFilters.h"
#include "sitkImageFilter.h"

namespace itk::simple
{

/** \class PasteImageFilter
 * \brief Paste an image (or a constant value) into another image.
 *
 * PasteImageFilter allows a region in a destination image to be filled with a source image or a constant pixel value.
 * The SetDestinationIndex() method
 * prescribes where in the destination input to start pasting data from the
 * source input.  The SetSourceRegion method prescribes the section of
 * the second image to paste into the first. When a constant pixel value is set, the SourceRegion describes the size
 * of the region filled. If the output requested
 * region does not include the SourceRegion after it has been
 * repositioned to DestinationIndex, then the output will just be
 * a copy of the input.
 *
 * This filter supports running "InPlace" to efficiently reuses the destination image buffer for the output, removing
 * the need to copy the destination pixels to the output.
 *
 * When the source image is a lower dimension than the destination image then the DestinationSkipAxes parameter
 * specifies which axes in the destination image are set to 1 when copying the region or filling with a constant.
 *
 */
class SITKBasicFilters_EXPORT PasteImageFilter : public ImageFilter
{
public:
  using Self = PasteImageFilter;

  /** Destructor */
  virtual ~PasteImageFilter();

  /** Default Constructor that takes no arguments and initializes
   * default parameters */
  PasteImageFilter();

  /** Define the pixels types supported by this filter */
  using PixelIDTypeList = NonLabelPixelIDTypeList;


  /**
   */
  SITK_RETURN_SELF_TYPE_HEADER
  SetSourceSize(std::vector<unsigned int> SourceSize)
  {
    this->m_SourceSize = std::move(SourceSize);
    return *this;
  }

  /**
   */
  std::vector<unsigned int>
  GetSourceSize() const
  {
    return this->m_SourceSize;
  }

  /**
   */
  SITK_RETURN_SELF_TYPE_HEADER
  SetSourceIndex(std::vector<int> SourceIndex)
  {
    this->m_SourceIndex = std::move(SourceIndex);
    return *this;
  }

  /**
   */
  std::vector<int>
  GetSourceIndex() const
  {
    return this->m_SourceIndex;
  }

  /**
   * Set/Get the destination index (where in the first input the second input will be pasted.
   */
  SITK_RETURN_SELF_TYPE_HEADER
  SetDestinationIndex(std::vector<int> DestinationIndex)
  {
    this->m_DestinationIndex = std::move(DestinationIndex);
    return *this;
  }

  /**
   * Set/Get the destination index (where in the first input the second input will be pasted.
   */
  std::vector<int>
  GetDestinationIndex() const
  {
    return this->m_DestinationIndex;
  }


  /** Set/Get the array describing which axes in the destination image to skip
   *
   * The axes with true values are set to 1, to fill the difference between the dimension of the input and source image.
   * The number of true value in DestinationSkipAxes plus the DestinationImageDimension must equal the
   * InputImageDimension.
   *
   * By default this array contains SourceImageDimension false values followed by true values for the remainder.
   */
  SITK_RETURN_SELF_TYPE_HEADER
  SetDestinationSkipAxes(std::vector<bool> DestinationSkipAxes)
  {
    this->m_DestinationSkipAxes = std::move(DestinationSkipAxes);
    return *this;
  }

  /** Set/Get the array describing which axes in the destination image to skip
   *
   * The axes with true values are set to 1, to fill the difference between the dimension of the input and source image.
   * The number of true values in DestinationSkipAxes plus the DestinationImageDimension must equal the
   * InputImageDimension.
   *
   * By default this array contains SourceImageDimension false values followed by true values for the remainder.
   */
  std::vector<bool>
  GetDestinationSkipAxes() const
  {
    return this->m_DestinationSkipAxes;
  }


  /** Name of this class */
  std::string
  GetName() const
  {
    return std::string("PasteImageFilter");
  }

  /** Print ourselves out */
  std::string
  ToString() const;


  /** Execute the filter on the input image */
#ifndef SWIG
  Image
  Execute(Image && destinationImage, const Image & sourceImage);
  Image
  Execute(Image && destinationImage, double constant);
#endif
  Image
  Execute(const Image & destinationImage, const Image & sourceImage);
  Image
  Execute(const Image & destinationImage, double constant);


private:
  /** Setup for member function dispatching */

  using MemberFunctionType = Image (Self::*)(const Image * destinationImage, const Image * sourceImage);
  template <class TImageType>
  Image
  ExecuteInternal(const Image * destinationImage, const Image * sourceImage);

  template <class TImageType, unsigned int OutputDimension>
  Image
  ExecuteInternal(const TImageType *                                    destinationImage,
                  const Image *                                         sourceImage,
                  std::integral_constant<unsigned int, OutputDimension> meta);
  template <class TImageType>
  Image
  ExecuteInternal(const TImageType *                      destinationImage,
                  const Image *                           sourceImage,
                  std::integral_constant<unsigned int, 1> meta);


  friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

  std::unique_ptr<detail::MemberFunctionFactory<MemberFunctionType>> m_MemberFactory;

  using MemberFunction2Type = Image (Self::*)(const Image * image, double constant);
  template <class TImageType>
  Image
  ExecuteInternal(const Image * image, double constant);
  friend struct detail::MemberFunctionAddressor<MemberFunction2Type>;
  std::unique_ptr<detail::MemberFunctionFactory<MemberFunction2Type>> m_MemberFactory2;


  std::vector<unsigned int> m_SourceSize{ std::vector<unsigned int>(SITK_MAX_DIMENSION, 1) };

  std::vector<int> m_SourceIndex{ std::vector<int>(SITK_MAX_DIMENSION, 0) };

  std::vector<int> m_DestinationIndex{ std::vector<int>(SITK_MAX_DIMENSION, 0) };

  std::vector<bool> m_DestinationSkipAxes{};

  bool m_InPlace{ false };
};

/**\
 * \brief Paste an image into another image.
 *
 * This function directly calls the execute method of PasteImageFilter
 * in order to support a procedural API
 *
 * \sa itk::simple::PasteImageFilter for the object oriented interface
 * @{
 */
#ifndef SWIG
SITKBasicFilters_EXPORT Image
Paste(Image &&                  destinationImage,
      const Image &             sourceImage,
      std::vector<unsigned int> sourceSize = std::vector<unsigned int>(SITK_MAX_DIMENSION, 1),
      std::vector<int>          sourceIndex = std::vector<int>(SITK_MAX_DIMENSION, 0),
      std::vector<int>          destinationIndex = std::vector<int>(SITK_MAX_DIMENSION, 0),
      std::vector<bool>         DestinationSkipAxes = std::vector<bool>());
#endif
SITKBasicFilters_EXPORT Image
Paste(const Image &             destinationImage,
      const Image &             sourceImage,
      std::vector<unsigned int> sourceSize = std::vector<unsigned int>(SITK_MAX_DIMENSION, 1),
      std::vector<int>          sourceIndex = std::vector<int>(SITK_MAX_DIMENSION, 0),
      std::vector<int>          destinationIndex = std::vector<int>(SITK_MAX_DIMENSION, 0),
      std::vector<bool>         DestinationSkipAxes = std::vector<bool>());

/** @} */
} // namespace itk::simple
#endif
