/*=========================================================================
*
*  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 sitkLabelShapeStatisticsImageFilter_h
#define sitkLabelShapeStatisticsImageFilter_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 LabelShapeStatisticsImageFilter
\brief Converts a label image to a label map and valuates the shape attributes.

A convenient class that converts a label image to a label map and valuates the shape attribute at once.

This implementation was taken from the Insight Journal paper: https://doi.org/10.54294/q6auw4 

\author Gaetan Lehmann. Biologie du Developpement et de la Reproduction, INRA de Jouy-en-Josas, France.


\see ShapeLabelObject , LabelShapeOpeningImageFilter , LabelStatisticsOpeningImageFilter

\sa itk::LabelImageToShapeLabelMapFilter for the Doxygen on the original ITK class.
     */
    class SITKBasicFilters_EXPORT LabelShapeStatisticsImageFilter : public ImageFilter {
    public:
      using Self = LabelShapeStatisticsImageFilter;

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

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

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

      /**
       * Set/Get the value used as "background" in the output image. Defaults to NumericTraits<PixelType>::NonpositiveMin() .
       */
      SITK_RETURN_SELF_TYPE_HEADER SetBackgroundValue ( double BackgroundValue ) { this->m_BackgroundValue = BackgroundValue; return *this; }

      /**
       * Set/Get the value used as "background" in the output image. Defaults to NumericTraits<PixelType>::NonpositiveMin() .
       */
      double GetBackgroundValue() const { return this->m_BackgroundValue; }\

      /**
       * Set/Get whether the maximum Feret diameter should be computed or not. Default value is false, because of the high computation time required.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetComputeFeretDiameter ( bool ComputeFeretDiameter ) { this->m_ComputeFeretDiameter = ComputeFeretDiameter; return *this; }

      /** Set the value of ComputeFeretDiameter to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER ComputeFeretDiameterOn() { return this->SetComputeFeretDiameter(true); }
      SITK_RETURN_SELF_TYPE_HEADER ComputeFeretDiameterOff() { return this->SetComputeFeretDiameter(false); }

      /**
       * Set/Get whether the maximum Feret diameter should be computed or not. Default value is false, because of the high computation time required.
       */
      bool GetComputeFeretDiameter() const { return this->m_ComputeFeretDiameter; }\

      /**
       * Set/Get whether the perimeter should be computed or not. Default value is false, because of the high computation time required.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetComputePerimeter ( bool ComputePerimeter ) { this->m_ComputePerimeter = ComputePerimeter; return *this; }

      /** Set the value of ComputePerimeter to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER ComputePerimeterOn() { return this->SetComputePerimeter(true); }
      SITK_RETURN_SELF_TYPE_HEADER ComputePerimeterOff() { return this->SetComputePerimeter(false); }

      /**
       * Set/Get whether the perimeter should be computed or not. Default value is false, because of the high computation time required.
       */
      bool GetComputePerimeter() const { return this->m_ComputePerimeter; }\

      /**
       * Set/Get whether the oriented bounding box should be computed or not. Default value is false because of potential memory consumption issues with sparse labels.
       */
      SITK_RETURN_SELF_TYPE_HEADER SetComputeOrientedBoundingBox ( bool ComputeOrientedBoundingBox ) { this->m_ComputeOrientedBoundingBox = ComputeOrientedBoundingBox; return *this; }

      /** Set the value of ComputeOrientedBoundingBox to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER ComputeOrientedBoundingBoxOn() { return this->SetComputeOrientedBoundingBox(true); }
      SITK_RETURN_SELF_TYPE_HEADER ComputeOrientedBoundingBoxOff() { return this->SetComputeOrientedBoundingBox(false); }

      /**
       * Set/Get whether the oriented bounding box should be computed or not. Default value is false because of potential memory consumption issues with sparse labels.
       */
      bool GetComputeOrientedBoundingBox() const { return this->m_ComputeOrientedBoundingBox; }
     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<unsigned int> GetBoundingBox(int64_t label) const { return this->m_pfGetBoundingBox(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<unsigned int> GetRegion(int64_t label) const { return this->m_pfGetRegion(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetCentroid(int64_t label) const { return this->m_pfGetCentroid(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetElongation(int64_t label) const { return this->m_pfGetElongation(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetEquivalentEllipsoidDiameter(int64_t label) const { return this->m_pfGetEquivalentEllipsoidDiameter(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetEquivalentSphericalPerimeter(int64_t label) const { return this->m_pfGetEquivalentSphericalPerimeter(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetEquivalentSphericalRadius(int64_t label) const { return this->m_pfGetEquivalentSphericalRadius(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetFeretDiameter(int64_t label) const { return this->m_pfGetFeretDiameter(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetFlatness(int64_t label) const { return this->m_pfGetFlatness(label); };

     /**
      *
      *
      * This is a measurement. Its value is updated in the Execute
      * methods, so the value will only be valid after an execution.
      */
     std::vector<int64_t> GetLabels() const { return this->m_Labels; };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     uint64_t GetNumberOfPixels(int64_t label) const { return this->m_pfGetNumberOfPixels(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     uint64_t GetNumberOfPixelsOnBorder(int64_t label) const { return this->m_pfGetNumberOfPixelsOnBorder(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetPerimeter(int64_t label) const { return this->m_pfGetPerimeter(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetPerimeterOnBorder(int64_t label) const { return this->m_pfGetPerimeterOnBorder(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetPerimeterOnBorderRatio(int64_t label) const { return this->m_pfGetPerimeterOnBorderRatio(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetPhysicalSize(int64_t label) const { return this->m_pfGetPhysicalSize(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetPrincipalAxes(int64_t label) const { return this->m_pfGetPrincipalAxes(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetPrincipalMoments(int64_t label) const { return this->m_pfGetPrincipalMoments(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     double GetRoundness(int64_t label) const { return this->m_pfGetRoundness(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetOrientedBoundingBoxSize(int64_t label) const { return this->m_pfGetOrientedBoundingBoxSize(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetOrientedBoundingBoxOrigin(int64_t label) const { return this->m_pfGetOrientedBoundingBoxOrigin(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetOrientedBoundingBoxDirection(int64_t label) const { return this->m_pfGetOrientedBoundingBoxDirection(label); };

     /**
      *
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<double> GetOrientedBoundingBoxVertices(int64_t label) const { return this->m_pfGetOrientedBoundingBoxVertices(label); };

     /**
      * Get an array of indexes for pixels with the label value.
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<unsigned int> GetIndexes(int64_t label) const { return this->m_pfGetIndexes(label); };

     /**
      * Get an array of run-length encoding (RLE) indexes for pixels with the label value. The array is the index of a starting line, followed by the length repeated. The length of the array is divisible by the image's dimension + 1. For example for a 2D image the array [ 2, 3, 2] would encode the two indexes [2,3] and [3,3].
      *
      * This is an active measurement. It may be accessed while the
      * filter is being executing in command call-backs and can be
      * accessed after execution.
      */
     std::vector<unsigned int> GetRLEIndexes(int64_t label) const { return this->m_pfGetRLEIndexes(label); };


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

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


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

      void Execute ( const Image& image1 );


      /** Does the specified label exist? Can only be called after a call a call to Update(). */
      bool HasLabel(int64_t label );

      /** Return the number of labels after execution. */
      uint64_t GetNumberOfLabels( );

    private:

      /** Setup for member function dispatching */

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


      friend struct detail::MemberFunctionAddressor<MemberFunctionType>;

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


      /*  */
      double  m_BackgroundValue{0};

      bool  m_ComputeFeretDiameter{false};

      bool  m_ComputePerimeter{true};

      bool  m_ComputeOrientedBoundingBox{false};

      /* Docs */
      std::function<std::vector<unsigned int>(int64_t)> m_pfGetBoundingBox;
      /* Docs */
      std::function<std::vector<unsigned int>(int64_t)> m_pfGetRegion;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetCentroid;
      /* Docs */
      std::function<double(int64_t)> m_pfGetElongation;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetEquivalentEllipsoidDiameter;
      /* Docs */
      std::function<double(int64_t)> m_pfGetEquivalentSphericalPerimeter;
      /* Docs */
      std::function<double(int64_t)> m_pfGetEquivalentSphericalRadius;
      /* Docs */
      std::function<double(int64_t)> m_pfGetFeretDiameter;
      /* Docs */
      std::function<double(int64_t)> m_pfGetFlatness;
      /* Docs */
      std::vector<int64_t> m_Labels{std::vector<int64_t>()};
      /* Docs */
      std::function<uint64_t(int64_t)> m_pfGetNumberOfPixels;
      /* Docs */
      std::function<uint64_t(int64_t)> m_pfGetNumberOfPixelsOnBorder;
      /* Docs */
      std::function<double(int64_t)> m_pfGetPerimeter;
      /* Docs */
      std::function<double(int64_t)> m_pfGetPerimeterOnBorder;
      /* Docs */
      std::function<double(int64_t)> m_pfGetPerimeterOnBorderRatio;
      /* Docs */
      std::function<double(int64_t)> m_pfGetPhysicalSize;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetPrincipalAxes;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetPrincipalMoments;
      /* Docs */
      std::function<double(int64_t)> m_pfGetRoundness;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetOrientedBoundingBoxSize;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetOrientedBoundingBoxOrigin;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetOrientedBoundingBoxDirection;
      /* Docs */
      std::function<std::vector<double>(int64_t)> m_pfGetOrientedBoundingBoxVertices;
      /* Docs */
      std::function<std::vector<unsigned int>(int64_t)> m_pfGetIndexes;
      /* Docs */
      std::function<std::vector<unsigned int>(int64_t)> m_pfGetRLEIndexes;

      // Holder of process object for active measurements
      itk::ProcessObject *m_Filter{nullptr};

    };


}
#endif
