/*=========================================================================
 *
 *  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
 *
 *         https://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 itkColorTable_h
#define itkColorTable_h

#include "itkObject.h"
#include "itkRGBPixel.h"
#include "itkObjectFactory.h"

#include <string>
#include <vector>
namespace itk
{
/** \class ColorTable
 *  \brief Define a color table for image visualisation.
 *
 * Generates color lookup tables of various types. The lookup table
 * value range differs for integral and continuous data types. Consult
 * the documentation for each lookup table generator.
 * \ingroup DataRepresentation
 * \ingroup ITKCommon
 */

template <typename TComponent>
class ITK_TEMPLATE_EXPORT ColorTable : public Object
{
public:
  ITK_DISALLOW_COPY_AND_MOVE(ColorTable);

  /** Standard class type aliases. */
  using Self = ColorTable;
  using Superclass = Object;
  using Pointer = SmartPointer<Self>;
  using ConstPointer = SmartPointer<const Self>;

  /** Method for creation through the object factory. */
  itkNewMacro(Self);

  /** \see LightObject::GetNameOfClass() */
  itkOverrideGetNameOfClassMacro(ColorTable);

  /** Generate a lookup table of 8 discrete colors. The colors are Red,
   * Purple, Aqua, Yellow, Green, Blue, Grey0.70, White. For integral
   * pixel types, the color range is between NonpositiveMin() and max(). For
   * continuous types, the range is 0.0 to 1.0.
   */
  void
  UseDiscreteColors();

  /** Generate a lookup table of n grayscale values. For integral pixel
   * types, a ramp is generated from NonpositiveMin() to max() of the
   * pixel type. For continuous pixel types, the range is 0.0 to 1.0.
   */
  void
  UseGrayColors(unsigned int n = 256);

  /** Generate a lookup table of n values good for showing
   * "temperatures".  For integral pixel types, the color range is
   * between NonpositiveMin() and max(). For continuous types, the
   * range is 0.0 to 1.0.
   */
  void
  UseHeatColors(unsigned int n = 256);

  /** Generate a lookup table of n random values. For integral pixel
   * types, the color range is between NonpositiveMin() and
   * max(). For continuous types, the range is 0.0 to 1.0.
   */
  void
  UseRandomColors(unsigned int n = 256);

  /** Get the number of colors in the lookup table. */
  itkGetConstMacro(NumberOfColors, unsigned int);

  /** Get the color stored at a given index. */
  RGBPixel<TComponent>
  GetColor(unsigned int c);

  /** Set the color at a given index. Optionally provide a name for
   * the color. If a name is not provided, the name "UserDefined" is
   * used.
   */
  /** @ITKStartGrouping */
  bool
  SetColor(unsigned int c, TComponent r, TComponent g, TComponent b, const char * name = "UserDefined");
  bool
  SetColor(unsigned int c, RGBPixel<TComponent> pixel, const char * name = "UserDefined");
  /** @ITKEndGrouping */
  /** Given the position in the table and the color
   * returns the value.
   */
  TComponent
  GetColorComponent(unsigned int c, char rgb);

  /** Get the name of the color at a given index. */
  std::string
  GetColorName(unsigned int c);

  /** Find the color closest to a given pixel. Uses a L2 distance
   * metric.
   */
  unsigned int
  GetClosestColorTableId(TComponent r, TComponent g, TComponent b);

protected:
  ColorTable() = default;
  void
  PrintSelf(std::ostream & os, Indent indent) const override;

private:
  using ColorNameVectorType = std::vector<std::string>;
  using ColorVectorType = std::vector<RGBPixel<TComponent>>;

  void
  DeleteColors();

  unsigned int m_NumberOfColors{ 0 };

  ColorNameVectorType m_ColorName{};
  ColorVectorType     m_Color{};
};
} // namespace itk

#ifndef ITK_MANUAL_INSTANTIATION
#  include "itkColorTable.hxx"
#endif

#endif
