/* **************************************************************************
                qgscolorrampshader.h -  description
                       -------------------
begin                : Fri Dec 28 2007
copyright            : (C) 2007 by Peter J. Ersts
email                : ersts@amnh.org

This class is based off of code that was originally written by Marco Hugentobler and
originally part of the larger QgsRasterLayer class
****************************************************************************/

/* **************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef QGSCOLORRAMPSHADER_H
#define QGSCOLORRAMPSHADER_H

#include <QColor>
#include <QMap>

#include "qgsrastershaderfunction.h"

/** \ingroup core
 * A ramp shader will color a raster pixel based on a list of values ranges in a ramp.
 */
class CORE_EXPORT QgsColorRampShader : public QgsRasterShaderFunction
{

  public:
    QgsColorRampShader( double theMinimumValue = 0.0, double theMaximumValue = 255.0 );

    //An entry for classification based upon value.
    //Such a classification is typically used for
    //single band layers where a pixel value represents
    //not a color but a quantity, e.g. temperature or elevation
    struct ColorRampItem
    {
      QString label;
      double value;
      QColor color;

      // compare operator for sorting
      bool operator<( const ColorRampItem& other ) const { return value < other.value; }
    };

    enum ColorRamp_TYPE
    {
      INTERPOLATED,
      DISCRETE,
      EXACT
    };

    /** \brief Get the custom colormap*/
    QList<QgsColorRampShader::ColorRampItem> colorRampItemList() const {return mColorRampItemList;}

    /** \brief Get the color ramp type */
    QgsColorRampShader::ColorRamp_TYPE colorRampType() {return mColorRampType;}

    /** \brief Get the color ramp type as a string */
    QString colorRampTypeAsQString();

    /** \brief Get the maximum size the color cache can be*/
    int maximumColorCacheSize() { return mMaximumColorCacheSize; }

    /** \brief Set custom colormap */
    void setColorRampItemList( const QList<QgsColorRampShader::ColorRampItem>& theList ) { mColorRampItemList = theList; } //TODO: sort on set

    /** \brief Set the color ramp type*/
    void setColorRampType( QgsColorRampShader::ColorRamp_TYPE theColorRampType );

    /** \brief Set the color ramp type*/
    void setColorRampType( QString );

    /** \brief Set the maximum size the color cache can be */
    void setMaximumColorCacheSize( int theSize ) { mMaximumColorCacheSize = theSize; }

    /** \brief Generates and new RGB value based on one input value */
    bool shade( double, int*, int*, int* );

    /** \brief Generates and new RGB value based on original RGB value */
    bool shade( double, double, double, int*, int*, int* );

  private:
    /** Current index from which to start searching the color table*/
    int mCurrentColorRampItemIndex;

    //TODO: Consider pulling this out as a separate class and internally storing as a QMap rather than a QList
    /** This vector holds the information for classification based on values. Each item holds a value, a label and a color. The member mDiscreteClassification holds if one color is applied for all values between two class breaks (true) or if the item values are (linearly) interpolated for values between the item values (false)*/
    QList<QgsColorRampShader::ColorRampItem> mColorRampItemList;

    /** \brief The color ramp type */
    QgsColorRampShader::ColorRamp_TYPE mColorRampType;

    /** \brief Cache of values that have already been looked up */
    QMap<double, QColor> mColorCache;

    /** Maximum size of the color cache. The color cache could eat a ton of memory if you have 32-bit data */
    int mMaximumColorCacheSize;



    /** Gets the color for a pixel value from the classification vector mValueClassification. Assigns the color of the lower class for every pixel between two class breaks.*/
    bool discreteColor( double, int*, int*, int* );

    /** Gets the color for a pixel value from the classification vector mValueClassification. Assigns the color of the exact matching value in the color ramp item list */
    bool exactColor( double, int*, int*, int* );

    /** Gets the color for a pixel value from the classification vector mValueClassification. Interpolates the color between two class breaks linearly.*/
    bool interpolatedColor( double, int*, int*, int* );
};

#endif
