/*=========================================================================
*
*  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 sitkLabelStatisticsImageFilter_h
#define sitkLabelStatisticsImageFilter_h

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

#include <memory>

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

namespace itk::simple {

    /**\class LabelStatisticsImageFilter
\brief Given an intensity image and a label map, compute min, max, variance and mean of the pixels associated with each label or segment.

LabelStatisticsImageFilter computes the minimum, maximum, sum, mean, median, variance and sigma of regions of an intensity image, where the regions are defined via a label map (a second input). The label image should be integral type. The filter needs all of its input image. It behaves as a filter with an input and output. Thus it can be inserted in a pipeline with other filters and the statistics will only be recomputed if a downstream filter changes.

Optionally, the filter also computes intensity histograms on each object. If histograms are enabled, a median intensity value can also be computed, although its accuracy is limited to the bin width of the histogram. If histograms are not enabled, the median returns zero.

This filter is automatically multi-threaded and can stream its input when NumberOfStreamDivisions is set to more than
\li Statistics are independently computed for each streamed and threaded region then merged.

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

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

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

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

\

      /**
       */
      SITK_RETURN_SELF_TYPE_HEADER SetUseHistograms ( bool UseHistograms ) { this->m_UseHistograms = UseHistograms; return *this; }

      /** Set the value of UseHistograms to true or false respectfully. */
      SITK_RETURN_SELF_TYPE_HEADER UseHistogramsOn() { return this->SetUseHistograms(true); }
      SITK_RETURN_SELF_TYPE_HEADER UseHistogramsOff() { return this->SetUseHistograms(false); }

      /**
       */
      bool GetUseHistograms() const { return this->m_UseHistograms; }
     /**
      * Return the computed Minimum for a 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 GetMinimum(int64_t label) const { return this->m_pfGetMinimum(label); };

     /**
      * Return the computed Maximum for a 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 GetMaximum(int64_t label) const { return this->m_pfGetMaximum(label); };

     /**
      * Return the computed Mean for a 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 GetMean(int64_t label) const { return this->m_pfGetMean(label); };

     /**
      * Return the computed Median for a label. Requires histograms to be enabled!
      *
      * 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 GetMedian(int64_t label) const { return this->m_pfGetMedian(label); };

     /**
      * Return the computed Standard Deviation for a 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 GetSigma(int64_t label) const { return this->m_pfGetSigma(label); };

     /**
      * Return the computed Variance for a 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 GetVariance(int64_t label) const { return this->m_pfGetVariance(label); };

     /**
      * Return the compute Sum for a 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 GetSum(int64_t label) const { return this->m_pfGetSum(label); };

     /**
      * Return the number of pixels for a 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 GetCount(int64_t label) const { return this->m_pfGetCount(label); };

     /**
      * Return the computed bounding box for a label. A vector of minIndex, maxIndex pairs for each axis. The intervals include the endpoints.
      *
      * 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<int> GetBoundingBox(int64_t label) const { return this->m_pfGetBoundingBox(label); };

     /**
      * Return the computed region.
      *
      * 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 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; };


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

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


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

      void Execute ( const Image & image, const Image & labelImage );


      /** 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 * image, const Image * labelImage );

      friend struct detail::DualExecuteInternalAddressor<MemberFunctionType>;
      template <class TImageType1, class TImageType2> void DualExecuteInternal ( const Image * image, const Image * labelImage );


      std::unique_ptr<detail::DualMemberFunctionFactory<MemberFunctionType> > m_DualMemberFactory;



      bool  m_UseHistograms{true};


      std::function<double(int64_t)> m_pfGetMinimum;

      std::function<double(int64_t)> m_pfGetMaximum;

      std::function<double(int64_t)> m_pfGetMean;

      std::function<double(int64_t)> m_pfGetMedian;

      std::function<double(int64_t)> m_pfGetSigma;

      std::function<double(int64_t)> m_pfGetVariance;

      std::function<double(int64_t)> m_pfGetSum;

      std::function<uint64_t(int64_t)> m_pfGetCount;

      std::function<std::vector<int>(int64_t)> m_pfGetBoundingBox;

      std::function<std::vector<unsigned int>(int64_t)> m_pfGetRegion;

      std::vector<int64_t> m_Labels{std::vector<int64_t>()};

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

    };


}
#endif
