/*****************************************************************************
 * $CAMITK_LICENCE_BEGIN$
 *
 * CamiTK - Computer Assisted Medical Intervention ToolKit
 * (c) 2001-2025 Univ. Grenoble Alpes, CNRS, Grenoble INP - UGA, TIMC, 38000 Grenoble, France
 *
 * Visit http://camitk.imag.fr for more information
 *
 * This file is part of CamiTK.
 *
 * CamiTK is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License version 3
 * only, as published by the Free Software Foundation.
 *
 * CamiTK is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License version 3 for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * version 3 along with CamiTK.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $CAMITK_LICENCE_END$
 ****************************************************************************/

#ifndef ImageLutModel_H
#define ImageLutModel_H

#include <vtkImageData.h>
#include <vtkSmartPointer.h>

/**
 * @ingroup group_sdk_actions_image_lut
 *
 * @brief
 * The class ImageLutModel model the histogram of a given vtkImageData
 *
 * Uses double data type to manage the histogram. This allows for managin properly all
 * type of voxel datatype.
 *
 * @note
 * The ui is defined in the corresponding ImageLutWidget.ui
 *
 */

class ImageLutModel {
public:
    /// Constructor: set the image data
    ImageLutModel(vtkSmartPointer<vtkImageData>);

    /// destructor
    ~ImageLutModel();

    /// get the minimal voxel value (lutMin)
    double getMinValue();

    /// get the maximal voxel value (lutMax)
    double getMaxValue();

    /// change the number of bins
    void setNumberOfBins(int);

    /// get the current number of bins
    int getNumberOfBins();

    /// get the highgest grey level value
    double getMaxBinValue();

    /// get the number of voxels that end up in a given bin index
    double getBinValue(int);

    /// image value to the histogram bin index (get the bin index of a given value)
    int getBinIndex(double);

    /// image value to the histogram value (required to show the current level/window values on the graph)
    /// @param checkBound if true, then value below lutMin and over lutMax return 0 and getNumberOfBins() - 1 respectively
    /// @param value the pixel/voxel value to check the bin of
    double getBinIndexAsDouble(double value, bool checkBound = true);

    /// get level value as a percentage between 0 and 100
    int getPercentFromLevel(double);

    /// get level value from a percentage
    double getLevelFromPercent(int);

    /// get window value as a percentage between 0 and 100
    int getPercentFromWindow(double);

    /// get window value from a percentage
    double getWindowFromPercent(int);

private:
    /// update the histogram depending on the number of bins
    void updateHistogram();

    /// currently modeled image
    vtkSmartPointer<vtkImageData> image;

    /// Min the possible data value (given by the data type of the image)
    double minValue;

    /// Min the possible data value (given by the data type of the image)
    double maxValue;

    /// Table containing histogram bins \note use double as it can have a high number of pixel of the same number
    double* greyLevels;

    /// highest number of grey level (highest value in greyLevels array) \note use double as it can have a high number of pixel of the same number
    double highestGreyLevel;

    /// size of greyLevels \note the maximum number of histogram bins is UINT_MAX
    unsigned int nbHistoBins;

};

#endif // ImageLutModel_H
