/*=========================================================================
*
*  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 sitkFFTPadImageFilter_h
#define sitkFFTPadImageFilter_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 FFTPadImageFilter
\brief Pad an image to make it suitable for an FFT transformation.

FFT filters usually requires a specific image size. The size is decomposed in several prime factors, and the filter only supports prime factors up to a maximum value. This filter automatically finds the greatest prime factor required by the available implementation and pads the input appropriately.

This code was adapted from the Insight Journal contribution:

"FFT Based Convolution" by Gaetan Lehmann https://doi.org/10.54294/0iky0u 

\author Gaetan Lehmann


\see FFTShiftImageFilter
\sa itk::simple::FFTPad for the procedural interface
\sa itk::FFTPadImageFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT FFTPadImageFilter : public ImageFilter {
    public:
      using Self = FFTPadImageFilter;

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

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

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


      typedef enum {ZERO_PAD,ZERO_FLUX_NEUMANN_PAD,PERIODIC_PAD} BoundaryConditionType;\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetBoundaryCondition ( BoundaryConditionType BoundaryCondition ) { this->m_BoundaryCondition = BoundaryCondition; return *this; }

      /**
       */
      BoundaryConditionType GetBoundaryCondition() const { return this->m_BoundaryCondition; }\

      /**
       * Set/Get the greatest prime factor allowed on the size of the padded image. The filter increase the size of the image to reach a size with the greatest prime factor smaller or equal to the specified value. The default value is 5 for VNL, which is the greatest prime number for which the FFT are precomputed in FFTW, and thus gives very good performance. A greatest prime factor of 2 produce a size which is a power of 2, and thus is suitable for vnl base fft filters. A greatest prime factor of 1 or less - typically 0 - disable the extra padding.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetSizeGreatestPrimeFactor ( int SizeGreatestPrimeFactor ) { this->m_SizeGreatestPrimeFactor = SizeGreatestPrimeFactor; return *this; }

      /**
       * Set/Get the greatest prime factor allowed on the size of the padded image. The filter increase the size of the image to reach a size with the greatest prime factor smaller or equal to the specified value. The default value is 5 for VNL, which is the greatest prime number for which the FFT are precomputed in FFTW, and thus gives very good performance. A greatest prime factor of 2 produce a size which is a power of 2, and thus is suitable for vnl base fft filters. A greatest prime factor of 1 or less - typically 0 - disable the extra padding.
       */
      int GetSizeGreatestPrimeFactor() const { return this->m_SizeGreatestPrimeFactor; }

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

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


      /** Execute the filter on the input image */

      Image Execute ( const Image& image1 );


      /** The largest prime factor supported by underlying FFT implementation (FFTW or VNL). */
      static int DefaultSizeGreatestPrimeFactor( );

    private:

      /** Setup for member function dispatching */

      using MemberFunctionType = Image (Self::*)( const Image& image1 );
      template <class TImageType> Image ExecuteInternal ( const Image& image1 );


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

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


      BoundaryConditionType  m_BoundaryCondition{itk::simple::FFTPadImageFilter::ZERO_FLUX_NEUMANN_PAD};

      int  m_SizeGreatestPrimeFactor{itk::simple::FFTPadImageFilter::DefaultSizeGreatestPrimeFactor()};


    };

    /**\
     * \brief Pad an image to make it suitable for an FFT transformation.
     *
     * This function directly calls the execute method of FFTPadImageFilter
     * in order to support a procedural API
     *
     * \sa itk::simple::FFTPadImageFilter for the object oriented interface
     * @{
     */

     SITKBasicFilters_EXPORT Image FFTPad ( const Image& image1, FFTPadImageFilter::BoundaryConditionType boundaryCondition = itk::simple::FFTPadImageFilter::ZERO_FLUX_NEUMANN_PAD, int sizeGreatestPrimeFactor = itk::simple::FFTPadImageFilter::DefaultSizeGreatestPrimeFactor() );

     /** @} */
}
#endif
