//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2016 Richard S. Smith and collaborators.
//
// If you use MorphoGraphX in your work, please cite:
//   http://dx.doi.org/10.7554/eLife.05864
//
// MorphoGraphX is free software, and is licensed under under the terms of the 
// GNU General (GPL) Public License version 2.0, http://www.gnu.org/licenses.
//
#ifndef COLORS_HPP
#define COLORS_HPP

#include <Config.hpp>

#include <Color.hpp>
#include <Parms.hpp>
#include <Util.hpp>

#include <QAbstractItemModel>
#include <QFont>
#include <QModelIndex>
#include <QString>
#include <QTextStream>
#include <vector>

namespace mgx 
{
  class mgx_EXPORT Colors : public QAbstractItemModel 
	{
    Q_OBJECT
  
  public:
    /// Mesh1 and 2 must have the same order for their colors
    enum ColorType {
      ///@{
      //\name First mesh
      Mesh1Color,           ///< Color of the lines
      Mesh1BorderColor,     ///< Color of the border
      // Mesh1PointColor,
      Mesh1SelectColor,     ///< Color of the selected points and edges
      Mesh1CellsColor,      ///< Color of the cell ids
      Stack1BBoxColor,      ///< Color of the bounding box
      ///@}
      ///@{
      //\name Second mesh
      Mesh2Color,           ///< Color of the lines
      Mesh2BorderColor,     ///< Color of the border
      // Mesh2PointColor,
      Mesh2SelectColor,     ///< Color of the selected points and edges
      Mesh2CellsColor,      ///< Color of the cell ids
      Stack2BBoxColor,      ///< Color of the bounding box
      ///@}
      ///@{
      //\name Others
      BackgroundColor,           ///< Color of the image background
      Clip1GridColor,            ///< Color of the grid of the 1st clipping planes
      Clip2GridColor,            ///< Color of the grid of the 2nd clipping planes
      Clip3GridColor,            ///< Color of the grid of the 3rd clipping planes
      CuttingPlaneGridColor,     ///< Color of the grid of the cutting surface
      LegendColor,               ///< Color of the text and lines in the color bar
      ScaleBarColor,             ///< Color of the text and lines in the scale bar
      VoxelEditColor,            ///< Color of the xircle for the pixel edit tool
      ///@}
      ///@{
      //\name Summary
      NbColors,                         ///< Total number of colors
      StartMesh1 = Mesh1Color,          ///< First id for the mesh2 colors
      StartMesh2 = Mesh2Color,          ///< First id for the mesh2 colors
      StartOthers = BackgroundColor     ///< First id for the other colors
        ///@}
    };
  
    static const QString colorNames[NbColors];
    static const QString categoryNames[3];
    static const int categoryShift[3];
    static const int categorySize[3];
  
    Colors();
    virtual ~Colors() {}
  
    void readParms(Parms& parms, QString section);
    void writeParms(QTextStream& pout, QString section);
  
    bool hasChildren(const QModelIndex& parent = QModelIndex()) const;
  
    QColor color(const QModelIndex& index) const 
		{
      return data(index, Qt::DecorationRole).value<QColor>();
    }
    void setColor(const QModelIndex& index, QColor col) 
		{
      setData(index, col, Qt::DecorationRole);
    }
  
    QColor qcolor(ColorType type) const { return colors[type]; }
    Colorf color(ColorType type) const { return (Colorf)colors[type]; }
  
    int rowCount(const QModelIndex& parent = QModelIndex()) const;
    int columnCount(const QModelIndex& parent = QModelIndex()) const;
  
    Qt::ItemFlags flags(const QModelIndex& index) const;
  
    QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    bool setData(const QModelIndex& index, const QVariant& value, int role = Qt::EditRole);
    QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
  
    QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex& index) const;
  
    static Colors* instance()
    {
      if(_instance == 0)
        _instance = new Colors();
      return _instance;
    }
  
    static QColor getQColor(ColorType type) {
      return instance()->qcolor(type);
    }
  
    static Colorf getColor(ColorType type) {
      return instance()->color(type);
    }
  
  signals:
    void colorsChanged();
  
  public slots:
    void backupColors();
    void restoreColors();
    void resetColors();
  
  protected:
    std::vector<QColor> colors, backup;
    QFont _font;
    static Colors* _instance;
  };
}
#endif
