/*=========================================================================
 *
 *  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 itkTransformFactoryBaseRegister_hxx
#define itkTransformFactoryBaseRegister_hxx
#include "itkTransformFactory.h"
#include "itkVersion.h"

#include "itkAzimuthElevationToCartesianTransform.h"
#include "itkCenteredAffineTransform.h"
#include "itkCenteredEuler3DTransform.h"
#include "itkCenteredRigid2DTransform.h"
#include "itkCenteredSimilarity2DTransform.h"
#include "itkEuler2DTransform.h"
#include "itkFixedCenterOfRotationAffineTransform.h"
#include "itkIdentityTransform.h"
#include "itkQuaternionRigidTransform.h"
#if !defined ITK_LEGACY_REMOVE
// The v3 Rigid3DTransform will be removed in ITKv6
#  include "itkv3Rigid3DTransform.h"
#endif
#include "itkRigid3DPerspectiveTransform.h"
#include "itkScaleLogarithmicTransform.h"
#include "itkScaleVersor3DTransform.h"
#include "itkScaleSkewVersor3DTransform.h"
#include "itkComposeScaleSkewVersor3DTransform.h"
#include "itkSimilarity2DTransform.h"
#include "itkSimilarity3DTransform.h"
#include "itkTranslationTransform.h"
#include "itkBSplineTransform.h"
#include "itkCompositeTransform.h"

// Transforms from Filtering/DisplacementField/include
#include "itkBSplineExponentialDiffeomorphicTransform.h"
#include "itkBSplineSmoothingOnUpdateDisplacementFieldTransform.h"
#include "itkConstantVelocityFieldTransform.h"
#include "itkDisplacementFieldTransform.h"
#include "itkGaussianExponentialDiffeomorphicTransform.h"
#include "itkGaussianSmoothingOnUpdateDisplacementFieldTransform.h"
#include "itkGaussianSmoothingOnUpdateTimeVaryingVelocityFieldTransform.h"
#include "itkTimeVaryingBSplineVelocityFieldTransform.h"
#include "itkTimeVaryingVelocityFieldTransform.h"
#include "itkVelocityFieldTransform.h"

#if !defined(ITK_LEGACY_REMOVE)
#  include "itkBSplineDeformableTransform.h"
#endif

#ifndef ITK_TRANSFORM_FACTORY_MAX_DIM
#  define ITK_TRANSFORM_FACTORY_MAX_DIM 9
#endif


namespace itk
{


namespace
{

// Class to register generic transform for dimension D and lower
template <typename TParameterType, unsigned int D>
struct RegisterTransformsD
{
  static void
  Register()
  {
    TransformFactory<AffineTransform<TParameterType, D>>::RegisterTransform();
    TransformFactory<CompositeTransform<TParameterType, D>>::RegisterTransform();
    TransformFactory<IdentityTransform<TParameterType, D>>::RegisterTransform();
    TransformFactory<TranslationTransform<TParameterType, D>>::RegisterTransform();

    // register transforms of one less dimension
    RegisterTransformsD<TParameterType, D - 1>::Register();
  }
};

// Template specialized class to stop registering transform.
template <typename TParameterType>
struct RegisterTransformsD<TParameterType, 1>
{
  static void
  Register()
  {}
};
} // namespace

template <typename TParameterType>
void
TransformFactoryBase::RegisterTransformFactory()
{
  // All generic transforms for any dimension, are registered in a
  // recursive class 2-MAX_TRANSFORM_DIM
  RegisterTransformsD<TParameterType, ITK_TRANSFORM_FACTORY_MAX_DIM>::Register();

  //
  //   TParameterType FixedParameters instances (in alphabetical order)
  //

  TransformFactory<AzimuthElevationToCartesianTransform<TParameterType, 3>>::RegisterTransform();

  TransformFactory<BSplineTransform<TParameterType, 2, 3>>::RegisterTransform();
  TransformFactory<BSplineTransform<TParameterType, 3, 3>>::RegisterTransform();
#if !defined(ITK_LEGACY_REMOVE)
  TransformFactory<BSplineDeformableTransform<TParameterType, 2, 2>>::RegisterTransform();
  TransformFactory<BSplineDeformableTransform<TParameterType, 3, 3>>::RegisterTransform();
#endif

  TransformFactory<CenteredAffineTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<CenteredAffineTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<CenteredEuler3DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<CenteredRigid2DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<CenteredSimilarity2DTransform<TParameterType>>::RegisterTransform();


  TransformFactory<Euler2DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<Euler3DTransform<TParameterType>>::RegisterTransform();

  TransformFactory<FixedCenterOfRotationAffineTransform<TParameterType, 3>>::RegisterTransform();

  TransformFactory<QuaternionRigidTransform<TParameterType>>::RegisterTransform();

  TransformFactory<Rigid2DTransform<TParameterType>>::RegisterTransform();

#if !defined ITK_LEGACY_REMOVE
  // We cannot register Rigid3DTransform because in ITKv4 the NewMacro was removed.
  // Rigid3DTransforms are only intended to be used as a baseclass.
  // Consider VersorRigid3D as a much more stable (under optimization) registration type.
  // itk::v3::Rigid3DTransform is used as a wrapper to simply add the NewMacro.
  TransformFactory<v3::Rigid3DTransform<TParameterType>>::RegisterTransform();
#endif
  TransformFactory<Rigid3DPerspectiveTransform<TParameterType>>::RegisterTransform();

  TransformFactory<ScalableAffineTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<ScaleLogarithmicTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<ScaleSkewVersor3DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<ComposeScaleSkewVersor3DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<ScaleTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<ScaleTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<ScaleTransform<TParameterType, 4>>::RegisterTransform();
  TransformFactory<ScaleVersor3DTransform<TParameterType>>::RegisterTransform();

  TransformFactory<Similarity2DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<Similarity3DTransform<TParameterType>>::RegisterTransform();

  TransformFactory<VersorRigid3DTransform<TParameterType>>::RegisterTransform();
  TransformFactory<VersorTransform<TParameterType>>::RegisterTransform();

  TransformFactory<BSplineSmoothingOnUpdateDisplacementFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<BSplineSmoothingOnUpdateDisplacementFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<ConstantVelocityFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<ConstantVelocityFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<DisplacementFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<DisplacementFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<GaussianExponentialDiffeomorphicTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<GaussianExponentialDiffeomorphicTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<GaussianSmoothingOnUpdateDisplacementFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<GaussianSmoothingOnUpdateDisplacementFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<GaussianSmoothingOnUpdateTimeVaryingVelocityFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<GaussianSmoothingOnUpdateTimeVaryingVelocityFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<TimeVaryingBSplineVelocityFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<TimeVaryingBSplineVelocityFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<TimeVaryingVelocityFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<TimeVaryingVelocityFieldTransform<TParameterType, 3>>::RegisterTransform();
  TransformFactory<VelocityFieldTransform<TParameterType, 2>>::RegisterTransform();
  TransformFactory<VelocityFieldTransform<TParameterType, 3>>::RegisterTransform();
}

} // end namespace itk

#endif
