/***************************************************************************
  qgsvisibilitypresetcollection.h
  --------------------------------------
  Date                 : September 2014
  Copyright            : (C) 2014 by Martin Dobias
  Email                : wonder dot sk at gmail dot com
 ***************************************************************************
 *                                                                         *
 *   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 QGSVISIBILITYPRESETCOLLECTION_H
#define QGSVISIBILITYPRESETCOLLECTION_H

#include <QMap>
#include <QObject>
#include <QSet>
#include <QStringList>

class QDomDocument;
class QgsLayerTreeNode;
class QgsLayerTreeGroup;

/**
  \class QgsVisibilityPresetCollection
  \ingroup core
  \brief Container class that allows storage of visibility presets consisting of visible
   map layers and layer styles.
  \note added in QGIS 2.12
*/

class CORE_EXPORT QgsVisibilityPresetCollection : public QObject
{
    Q_OBJECT

  public:

    /** \ingroup core
     * Individual preset record of visible layers and styles.
     */
    class PresetRecord
    {
      public:

        bool operator==( const PresetRecord& other ) const
        {
          return mVisibleLayerIDs.toSet() == other.mVisibleLayerIDs.toSet()
                 && mPerLayerCheckedLegendSymbols == other.mPerLayerCheckedLegendSymbols
                 && mPerLayerCurrentStyle == other.mPerLayerCurrentStyle;
        }
        bool operator!=( const PresetRecord& other ) const
        {
          return !( *this == other );
        }

        //! Ordered list of layers that are visible
        QStringList mVisibleLayerIDs;
        /** For layers that have checkable legend symbols and not all symbols are checked - list which ones are
         * @note not available in Python bindings
         */
        QMap<QString, QSet<QString> > mPerLayerCheckedLegendSymbols;
        //! For layers that use multiple styles - which one is currently selected
        QMap<QString, QString> mPerLayerCurrentStyle;
    };

    QgsVisibilityPresetCollection();

    /** Returns whether a preset with a matching name exists.
     * @param name name of preset to check
     * @returns true if preset exists
     */
    bool hasPreset( const QString& name ) const;

    /** Inserts a new preset to the collection.
     * @param name name of preset
     * @param state preset record
     * @see update()
     */
    void insert( const QString& name, const PresetRecord& state );

    /** Updates a preset within the collection.
     * @param name name of preset to update
     * @param state preset record to replace existing preset
     * @see insert()
     */
    void update( const QString& name, const PresetRecord& state );

    /** Remove existing preset from collection.
     * @param name preset name
     */
    void removePreset( const QString& name );

    //! Remove all presets from the collection.
    void clear();

    //! Returns a list of existing preset names.
    QStringList presets() const;

    /** Returns the recorded state of a preset.
     * @param name name of preset
     */
    PresetRecord presetState( const QString& name ) const { return mPresets[name]; }

    /** Returns the list of layer IDs that should be visible for the specified preset.
     * @note The order of the returned list is not guaranteed to reflect the order of layers
     * in the canvas.
     * @param name preset name
     */
    QStringList presetVisibleLayers( const QString& name ) const;

    /** Apply check states of legend nodes of a given layer as defined in the preset.
     * @param name preset name
     * @param layerID layer ID
     */
    void applyPresetCheckedLegendNodesToLayer( const QString& name, const QString& layerID );

    /** Get layer style overrides (for QgsMapSettings) of the visible layers for given preset.
     * @param name preset name
     */
    QMap<QString, QString> presetStyleOverrides( const QString& name );

    /** Reads the preset collection state from XML
     * @param doc DOM document
     * @see writeXML
     */
    void readXML( const QDomDocument& doc );

    /** Writes the preset collection state to XML.
     * @param doc DOM document
     * @see readXML
     */
    void writeXML( QDomDocument& doc );

    /** Static method for adding visible layers from a layer tree group to a preset
     * record.
     * @param parent layer tree group parent
     * @param rec preset record to amend
     */
    static void addVisibleLayersToPreset( QgsLayerTreeGroup* parent, PresetRecord& rec );

  signals:

    /** Emitted when presets within the collection are changed.
     */
    void presetsChanged();

  protected slots:

    /** Handles updates of the preset collection when layers are removed from the registry
     */
    void registryLayersRemoved( const QStringList& layerIDs );

    //! Update style name if a stored style gets renamed
    void layerStyleRenamed( const QString& oldName, const QString& newName );

  protected:

    /** Reconnects all preset layers to handle style renames
     */
    void reconnectToLayersStyleManager();

    typedef QMap<QString, PresetRecord> PresetRecordMap;
    PresetRecordMap mPresets;
};


#endif // QGSVISIBILITYPRESETCOLLECTION_H
