/***************************************************************************
  qgsprocessingparametermeshdataset.h
  ---------------------
  Date                 : October 2020
  Copyright            : (C) 2020 by Vincent Cloarec
  Email                : vcloarec 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 QGSPROCESSINGPARAMETERMESHDATASET_H
#define QGSPROCESSINGPARAMETERMESHDATASET_H

#include "qgsmeshdataset.h"
#include "qgsprocessingoutputs.h"
#include "qgsprocessingparameters.h"
#include "qgsprocessingparametertype.h"

#include <QString>

using namespace Qt::StringLiterals;

/**
 * \brief A parameter for processing algorithms that need a list of mesh dataset groups.
 *
 * A valid value for this parameter is a list (QVariantList) of dataset groups index in the mesh layer scope
 * Dataset group index can be evaluated with the method valueAsDatasetGroup()
 *
 * \note This parameter is dependent on a mesh layer parameter (see QgsProcessingParameterMeshLayer)
 *
 * \ingroup core
 * \since QGIS 3.18
 */
class CORE_EXPORT QgsProcessingParameterMeshDatasetGroups : public QgsProcessingParameterDefinition
{
  public:
    /**
     * Constructor
     * \param name name of the parameter
     * \param description description of the parameter
     * \param meshLayerParameterName name of the associated mesh layer parameter
     * \param supportedDataType a set of QgsMeshDatasetGroupMetadata::DataType values for data types supported by the parameter
     * \param optional whether the parameter is optional
     */
    QgsProcessingParameterMeshDatasetGroups(
      const QString &name, const QString &description = QString(), const QString &meshLayerParameterName = QString(), QSet<int> supportedDataType = QSet<int>(), bool optional = false
    );

    QgsProcessingParameterDefinition *clone() const override SIP_FACTORY;
    QString type() const override;
    bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
    QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;
    QString asPythonString( QgsProcessing::PythonOutputType outputType = QgsProcessing::PythonOutputType::PythonQgsProcessingAlgorithmSubclass ) const override;
    QStringList dependsOnOtherParameters() const override;
    QVariantMap toVariantMap() const override;
    bool fromVariantMap( const QVariantMap &map ) override;

    //! Returns the type name for the parameter class.
    static QString typeName() { return u"meshdatasetgroups"_s; }

    //! Returns the name of the mesh layer parameter
    QString meshLayerParameterName() const;

    //! Returns whether the data type is supported by the parameter
    bool isDataTypeSupported( QgsMeshDatasetGroupMetadata::DataType dataType ) const;

    //! Returns the \a value as a list if dataset group indexes
    static QList<int> valueAsDatasetGroup( const QVariant &value );

  private:
    QString mMeshLayerParameterName;
    QSet<int> mSupportedDataType;

    static bool valueIsAcceptable( const QVariant &input, bool allowEmpty );
};

#ifndef SIP_RUN
///@cond PRIVATE

/**
 * \brief Parameter type definition for QgsProcessingParameterMeshDatasetGroups.
 *
 * \ingroup core
 * \since QGIS 3.18
 */
class CORE_EXPORT QgsProcessingParameterTypeMeshDatasetGroups : public QgsProcessingParameterType
{
  public:
    QgsProcessingParameterDefinition *create( const QString &name ) const override SIP_FACTORY { return new QgsProcessingParameterMeshDatasetGroups( name ); }

    QString description() const override { return QCoreApplication::translate( "Processing", "An input allowing selection dataset groups from a mesh layer" ); }

    QString name() const override { return QCoreApplication::translate( "Processing", "Mesh Dataset Groups" ); }

    QString id() const override { return QgsProcessingParameterMeshDatasetGroups::typeName(); }

    QString pythonImportString() const override { return u"from qgis.core import QgsProcessingParameterMeshDatasetGroups"_s; }

    QString className() const override { return u"QgsProcessingParameterMeshDatasetGroups"_s; }

    QStringList acceptedPythonTypes() const override { return QStringList() << QObject::tr( "list[int]: list of dataset group indexes, see QgsProcessingParameterMeshDatasetGroups docs" ); }

    QStringList acceptedParameterTypes() const override
    {
      return QStringList() << QgsProcessingParameterMeshDatasetGroups::typeName() << QgsProcessingParameterString::typeName() << QgsProcessingParameterNumber::typeName();
    }

    QStringList acceptedOutputTypes() const override { return QStringList() << QgsProcessingOutputString::typeName() << QgsProcessingOutputNumber::typeName(); }
};

///@endcond
#endif //SIP_RUN

/**
 * \brief A parameter for processing algorithms that need a list of mesh dataset index from time parameter.
 *
 * A valid value for this parameter is a map (QVariantMap) with in this form:
 *
 * - "type" : the type of time settings "current-context-time", "defined-date-time", "dataset-time-step" or "none" if all the dataset groups are static
 * - "value" : nothing if type is "static" or "current-context-time", QDateTime if "defined-date-time" or, for "dataset_time_step",  list of two int representing the dataset index that is the reference for the time step
 *
 * \note This parameter is dependent on a mesh layer parameter (\see QgsProcessingParameterMeshLayer)
 * and on mesh datast group parameter (\see QgsProcessingParameterMeshDatasetGroups)
 *
 * \ingroup core
 * \since QGIS 3.18
 */
class CORE_EXPORT QgsProcessingParameterMeshDatasetTime : public QgsProcessingParameterDefinition
{
  public:
    /**
     * Constructor
     * \param name name of the parameter
     * \param description description of the parameter
     * \param meshLayerParameterName name of the associated mesh layer parameter (\see QgsProcessingParameterMeshLayer)
     * \param datasetGroupParameterName name of the associated dataset group parameter (\see QgsProcessingParameterMeshDatasetGroups)
     */
    QgsProcessingParameterMeshDatasetTime(
      const QString &name, const QString &description = QString(), const QString &meshLayerParameterName = QString(), const QString &datasetGroupParameterName = QString()
    );

    QgsProcessingParameterDefinition *clone() const override SIP_FACTORY;
    QString type() const override;
    bool checkValueIsAcceptable( const QVariant &input, QgsProcessingContext *context = nullptr ) const override;
    QString valueAsPythonString( const QVariant &value, QgsProcessingContext &context ) const override;
    QString asPythonString( QgsProcessing::PythonOutputType outputType = QgsProcessing::PythonOutputType::PythonQgsProcessingAlgorithmSubclass ) const override;
    QStringList dependsOnOtherParameters() const override;
    QVariantMap toVariantMap() const override;
    bool fromVariantMap( const QVariantMap &map ) override;

    //! Returns the type name for the parameter class.
    static QString typeName() { return u"meshdatasettime"_s; }

    //! Returns the name of the mesh layer parameter
    QString meshLayerParameterName() const;

    //! Returns the name of the dataset groups parameter
    QString datasetGroupParameterName() const;

    /**
     * Returns the \a dataset value time type as a string :
     * current-context-time : the time is store in the processing context (e.g. current canvas time), in this case the value does not contain any time value
     * defined-date-time : absolute time of type QDateTime
     * dataset-time-step : a time step of existing dataset, in this case the time takes the form of a QMeshDatasetIndex with value to the corresponding dataset index
     * static : dataset groups are all static, in this case the value does not contain any time value
     */
    static QString valueAsTimeType( const QVariant &value );

    /**
     * Returns the \a value as a QgsMeshDatasetIndex if the value has "dataset-time-step" type.
     * If the value has the wrong type return an invalid dataset index
     *
     * \see valueAsTimeType()
     */
    static QgsMeshDatasetIndex timeValueAsDatasetIndex( const QVariant &value );

    /**
     * Returns the \a value as a QDateTime if the value has "defined-date-time" type.
     * If the value has the wrong type return an invalid QDatetime
     *
     * \see valueAsTimeType()
     */
    static QDateTime timeValueAsDefinedDateTime( const QVariant &value );

  private:
    QString mMeshLayerParameterName;
    QString mDatasetGroupParameterName;

    static bool valueIsAcceptable( const QVariant &input, bool allowEmpty );
};

#ifndef SIP_RUN
///@cond PRIVATE

/**
 * \brief Parameter type definition for QgsProcessingParameterMeshDatasetTime.
 *
 * \ingroup core
 * \since QGIS 3.18
 */
class CORE_EXPORT QgsProcessingParameterTypeMeshDatasetTime : public QgsProcessingParameterType
{
  public:
    QgsProcessingParameterDefinition *create( const QString &name ) const override SIP_FACTORY { return new QgsProcessingParameterMeshDatasetTime( name ); }

    QString description() const override { return QCoreApplication::translate( "Processing", "An input allowing selection of dataset index from a mesh layer by time setting" ); }

    QString name() const override { return QCoreApplication::translate( "Processing", "Mesh Dataset Time" ); }

    QString id() const override { return QgsProcessingParameterMeshDatasetTime::typeName(); }

    QString pythonImportString() const override { return u"from qgis.core import QgsProcessingParameterMeshDatasetTime"_s; }

    QString className() const override { return u"QgsProcessingParameterMeshDatasetTime"_s; }

    QStringList acceptedPythonTypes() const override { return QStringList() << QObject::tr( "dict{}: dictionary, see QgsProcessingParameterMeshDatasetTime docs" ); }

    QStringList acceptedParameterTypes() const override
    {
      return QStringList() << QgsProcessingParameterMeshDatasetTime::typeName() << QgsProcessingParameterString::typeName() << QgsProcessingParameterDateTime::typeName();
    }

    QStringList acceptedOutputTypes() const override { return QStringList() << QgsProcessingOutputString::typeName(); }
};

///@endcond
#endif //SIP_RUN


#endif // QGSPROCESSINGPARAMETERMESHDATASET_H
