/*============================================================================

The Medical Imaging Interaction Toolkit (MITK)

Copyright (c) German Cancer Research Center (DKFZ)
All rights reserved.

Use of this source code is governed by a 3-clause BSD license that can be
found in the LICENSE file.

============================================================================*/

#ifndef mitkManualSegmentationToSurfaceFilter_h
#define mitkManualSegmentationToSurfaceFilter_h

#include <MitkSegmentationExports.h>
#include <mitkImageToSurfaceFilter.h>

#include <vtkImageGaussianSmooth.h>
#include <vtkImageMedian3D.h>
#include <vtkImageResample.h>
#include <vtkImageThreshold.h>

namespace mitk
{
  /**
   * \brief Supplies a 3D surface from pre-processed segmentation.
   *
   * The resulting surface depends on a filter pipeline based on vtkMedian (1) and a Gaussian filter with
   * vtkImageGaussianSmooth (2).
   * All voxels can be changed to an isotropic representation of the
   * image (note: the number of voxels in the image will change). The
   * resulting isotropic image has 1mm isotropic voxels by default, but
   * can be varied freely.
   *
   * \ingroup Process
   */

  class MITKSEGMENTATION_EXPORT ManualSegmentationToSurfaceFilter : public ImageToSurfaceFilter
  {
  public:
    mitkClassMacro(ManualSegmentationToSurfaceFilter, ImageToSurfaceFilter);

    typedef double vtkDouble;

    /**
     * Will pre-process a segmentation voxelwise. The segmentation can use
     * a hole fill relating a median filter and smooth by a Gaussian
     * filter.
     * The image can be interpolated to an isotropic image.
     * By default every filter is disabled.
     * This method calls CreateSurface from mitkImageToSurfaceFilter and
     * does not need a manual call since we use Update().
     */
    void GenerateData() override;
    itkFactorylessNewMacro(Self);
    itkCloneMacro(Self);

      /**
       * Supplies a method for setting median filter by a bool value.
       */
      itkSetMacro(MedianFilter3D, bool);

    /**
     * Return state if median filter is enabled.
     */
    itkGetConstMacro(MedianFilter3D, bool);

    /**
     * Enable the median filter (first filter in pipeline).
     */
    itkBooleanMacro(MedianFilter3D);

    /**
     * Supplies a method to enable Interpolation.
     */
    itkSetMacro(Interpolation, bool);

    /**
     * Returns activation state of interpolation filter.
     */
    itkGetConstMacro(Interpolation, bool);

    /**
     * Enable the interpolation filter (second filter in pipeline) for
     * isotropic voxel.
     */
    itkBooleanMacro(Interpolation);

    /**
     * Supplies a method for Gaussian filter (third filter in pipeline).
     */
    itkSetMacro(UseGaussianImageSmooth, bool);

    /**
     * Returns activation state of standard deviation filter.
     */
    itkGetConstMacro(UseGaussianImageSmooth, bool);

    /**
     *  Enables Gaussian image smooth. As well the threshold for the
     *  CreateSurface() method will raise the threshold to 49 and changes
     *  the image range set  from 0 to 100. It is made for reasons in
     *  binary images to prevent conflicts with the used filter. There are
     *  better results for dividing fore- and background.
     */
    itkBooleanMacro(UseGaussianImageSmooth);

    /**
     * Set standard deviation for Gaussian Filter.
     * @param _arg by default 1.5
     */
    itkSetMacro(GaussianStandardDeviation, double);

    /**
     * Returns the standard deviation of the Gaussian filter which will be
     * used when filter is enabled.
     */
    itkGetConstMacro(GaussianStandardDeviation, double);

    /**
     * Set the Kernel for Median3DFilter. By default kernel is set to 3x3x3.
     * If you choose '1' nothing will be processed in this direction.
     */
    void SetMedianKernelSize(int x, int y, int z);

    /**
     * Returns the kernel size in the first direction.
     */
    itkGetConstMacro(MedianKernelSizeX, int);

    /**
     * Returns the kernel size in the second direction.
     */
    itkGetConstMacro(MedianKernelSizeY, int);

    /**
     * Returns the kernel size in the third direction.
     */
    itkGetConstMacro(MedianKernelSizeZ, int);

    /**
     * Set the values for Spacing in X, Y and Z-Dimension
     */
    void SetInterpolation(vtkDouble x, vtkDouble y, vtkDouble z);

  protected:
    ManualSegmentationToSurfaceFilter();
    ~ManualSegmentationToSurfaceFilter() override;

    bool m_MedianFilter3D;
    int m_MedianKernelSizeX, m_MedianKernelSizeY, m_MedianKernelSizeZ;
    bool m_UseGaussianImageSmooth; // Gaussian Filter
    double m_GaussianStandardDeviation;
    bool m_Interpolation;

    vtkDouble m_InterpolationX;
    vtkDouble m_InterpolationY;
    vtkDouble m_InterpolationZ;

  }; // namespace
}
#endif
