//
// This file is part of MorphoGraphX - http://www.MorphoGraphX.org
// Copyright (C) 2012-2019 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 PROCESS_PARMS_HPP
#define PROCESS_PARMS_HPP

#include <Config.hpp>
#include <Hash.hpp>
#include <Misc.hpp>

#include <QStringList>
#include <QHash>
#include <QIcon>
#include <unordered_map>

namespace mgx 
{
  /**
   * Type of the dictionary giving the list of possible strings for each argument.
   *
   * If the choice is free, the position should just not be present in the dictionnary.
   * \ingroup ProcessUtils
   */
  typedef QList<QStringList> ParmChoiceList;

  class mgx_EXPORT ProcessParms
  {
  public:
    ProcessParms() 
    { 
      setIcon(QIcon(":images/Default.png"));
    }
    virtual ~ProcessParms() {}

    /**
     * Process name that is using the parameters
     *
     * Note that the name must be a valid identifier in Python once the spaces are replaced by underscores. 
     * The name can contain spaces, but should not contain underscores or slashes. Slashed are translated 
     * double underscore, so double spaces are not allowed.
     */
    QString name() const;

    /**
     * Process description
     */
    QString description() const;

    /**
     * List of named parameters.
     *
     * There must be as many parameters than defaults.
     */
    QStringList parmNames() const;

    /**
     * List of parameters descriptions.
     *
     * There must be as many parameters than defaults.
     */
    QStringList parmDescs() const;

    /**
     * List of default parms.
     */
    QStringList parmDefaults() const;

    /**
     * Allows the parameter to have a pick list in the GUI. Note that no mechanism forces 
     * the user to choose one the choices in the list, any text may still be entered.
     */
    ParmChoiceList parmChoice() const;
    /**
     * Helper function that provides a list of choices for a boolean argument
     */
    static QStringList booleanChoice() { return QStringList() << "Yes" << "No"; }
	  /**
     * Helper function that provides a list of choices for choosing from the main or work stack
     */
    static QStringList storeChoice() { return QStringList() << "Main" << "Work"; } 
	  /**
     * Helper function that provides a list of choices for choosing between stack 1 and 2
     */
    static QStringList stackChoice() { return QStringList() << "Stack 1" << "Stack 2" << "Current" << "Other"; } 
	  /**
     * Helper function that provides a list of choices for choosing between stack 1 and 2
     */
    static QStringList meshChoice() { return QStringList() << "Mesh 1" << "Mesh 2" << "Current" << "Other"; } 
	  /**
     * Helper function that provides a list of choices for choosing the dimension
     */
    static QStringList dimensionChoice() { return QStringList() << "Vertices" << "Edges" << "Faces" << "Volumes"; } 
	  /**
     * Helper function that provides a list of choices for choosing the dimension
     */
    static QStringList dimChoice() { return QStringList() << "Vertices" << "Faces" << "Volumes" << "All"; } 

    /**
     * Icon to use to represent the process in the GUI.
     *
     * To use an icon present in the resources, you must precede the path with a colon
     *   ":/images/myicon.png".
     */
    QIcon icon() const;

    /**
     * Get a single parameter value by name
     */
    QString parm(const QString &name) const;

    /**
     * Get the list of parameter values
     */
    const QStringList &getParms();

    /**
     * Set the name
     */
    bool setName(const QString &name);

    /**
     * Set the description
     */
    bool setDesc(const QString &description);

    /**
     * Add a parameter to the list
     */
    bool addParm(const QString &parmName, const QString &desc, const QString &def, const QStringList &choices = QStringList());

    /**
     * Insert a parameter to the list
     */
    bool insertParm(const QString &parmName, const QString &desc, const QString &def, int pos, const QStringList &choices = QStringList());

    /**
     * Set the parameter's value
     */
    bool setParm(const QString &parmName, const QString &parm);

    /**
     * Set all the parameter values
     */
    bool setParms(const QStringList &parms);

    /**
     * Set the parameter's description
     */
    bool setParmDesc(const QString &parmName, const QString &desc);

    /**
     * Set the parameter's default value
     */
    bool setParmDefault(const QString &parmName, const QString &def);

    /**
     * Set the parameter's choices
     */
    bool setParmChoices(const QString &parmName, const QStringList &choices);

    /**
     * Set the icon
     */
    bool setIcon(const QIcon &icon);

    /**
     * Return a list of parameter names
     */
    QStringList parmList(const QString &key = QString()) const;

  private:
    QString _name;
    QString _description;
    QStringList _parms;
    std::unordered_map<QString, int> _parmIdx;
    QStringList _parmNames;
    QStringList _parmDescs;
    QStringList _parmDefaults;
    ParmChoiceList _parmChoices;
    QIcon _icon;
  };
}
#endif
