/***************************************************************************
    qgsmimedatautils.h
    ---------------------
    begin                : November 2011
    copyright            : (C) 2011 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 QGSMIMEDATAUTILS_H
#define QGSMIMEDATAUTILS_H

#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgswkbtypes.h"

#include <QMimeData>
#include <QString>
#include <QStringList>

using namespace Qt::StringLiterals;

class QgsLayerItem;
class QgsLayerTreeNode;
class QgsVectorLayer;
class QgsRasterLayer;
class QgsMeshLayer;
class QgsMapLayer;

/**
 * \ingroup core
 * \class QgsMimeDataUtils
 * \brief Contains utility functions for working with MIME data.
 */
class CORE_EXPORT QgsMimeDataUtils
{
  public:
    struct CORE_EXPORT Uri
    {
        //! Constructs invalid URI
        Uri() = default;
        //! Constructs URI from encoded data
        explicit Uri( const QString &encData );

        /**
       * Constructs a URI corresponding to the specified \a layer.
       *
       * \since QGIS 3.8
       */
        explicit Uri( QgsMapLayer *layer );

        /**
       * Returns whether the object contains valid data
       */
        bool isValid() const { return !layerType.isEmpty(); }

        //! Returns encoded representation of the object
        QString data() const;

        /**
       * Gets vector layer from uri if possible, otherwise returns NULLPTR and error is set
       * \param owner set to TRUE if caller becomes owner
       * \param error set to error message if cannot get vector
       */
        QgsVectorLayer *vectorLayer( bool &owner, QString &error ) const;

        /**
       * Gets raster layer from uri if possible, otherwise returns NULLPTR and error is set
       * \param owner set to TRUE if caller becomes owner
       * \param error set to error message if cannot get raster
       */
        QgsRasterLayer *rasterLayer( bool &owner, QString &error ) const;

        /**
       * Gets mesh layer from uri if possible, otherwise returns NULLPTR and error is set
       * \param owner set to TRUE if caller becomes owner
       * \param error set to error message if cannot get raster
       */
        QgsMeshLayer *meshLayer( bool &owner, QString &error ) const;

        /**
       * Returns the layer from the active project corresponding to this uri (if possible),
       * otherwise returns NULLPTR.
       *
       * Unlike vectorLayer(), rasterLayer(), or meshLayer(), this method will not attempt
       * to create a new layer corresponding to the URI.
       *
       * \since QGIS 3.8
       */
        QgsMapLayer *mapLayer() const;

        /**
       * Type of URI.
       *
       * Recognized types include
       *
       * - "vector": vector layers
       * - "raster": raster layers
       * - "mesh": mesh layers
       * - "point-cloud": point cloud layers (spelled with a dash since QGIS 3.42.0. In prior versions, there was no dash)
       * - "vector-tile": vector tile layers
       * - "tiled-scene": tiled scene layers
       * - "annotation": annotation layers
       * - "group": group layers
       * - "plugin": plugin layers
       * - "custom": custom types
       * - "project": QGS/QGZ project file
       * - "directory": directory path
       *
       * Note: use QgsMapLayerFactory::typeToString() to convert from a
       * Qgis::LayerType to a string (except for "custom", "project" and
       * "directory")
       *
       * Mime data from plugins may use additional custom layer types.
       */
        QString layerType;

        /**
       * For "vector" / "raster" type: provider id.
       * For "plugin" type: plugin layer type name.
       * For "custom" type: key of its QgsCustomDropHandler
       * For "project" and "directory" types: unused
       */
        QString providerKey;

        //! Human readable name to be used e.g. in layer tree
        QString name;
        //! Identifier of the data source recognized by its providerKey
        QString uri;
        QStringList supportedCrs;
        QStringList supportedFormats;

        /**
       * Layer ID, if uri is associated with a layer from a QgsProject.
       * \since QGIS 3.8
       */
        QString layerId;

        /**
       * Unique ID associated with application instance. Can be used to identify
       * if mime data was created inside the current application instance or not.
       * \since QGIS 3.8
       */
        QString pId;

        /**
       * WKB type, if associated with a vector layer, or QgsWkbTypes::Unknown if not
       * yet known.
       *
       * \since QGIS 3.8
       */
        Qgis::WkbType wkbType = Qgis::WkbType::Unknown;

        /**
       * Path to file, if uri is associated with a file.
       * \since QGIS 3.22
       */
        QString filePath;

#ifdef SIP_RUN
        // clang-format off
      SIP_PYOBJECT __repr__();
      % MethodCode
      QString str = u"<QgsMimeDataUtils::Uri (%1): %2>"_s.arg( sipCpp->providerKey, sipCpp->uri );
      sipRes = PyUnicode_FromString( str.toUtf8().constData() );
      % End
// clang-format on
#endif
    };
    typedef QList<QgsMimeDataUtils::Uri> UriList;

    /**
     * Encodes a URI list to a new QMimeData object.
     */
    static QMimeData *encodeUriList( const UriList &layers ) SIP_FACTORY;

    static bool isUriList( const QMimeData *data );

    static UriList decodeUriList( const QMimeData *data );

    /**
     * Returns encoded URI list from a list of layer tree nodes.
     */
    static QByteArray layerTreeNodesToUriList( const QList<QgsLayerTreeNode *> &nodes );

    /**
     * Returns TRUE if \a uri originated from the current QGIS application
     * instance.
     *
     * \since QGIS 3.8
     */
    static bool hasOriginatedFromCurrentAppInstance( const QgsMimeDataUtils::Uri &uri );

  private:
    static QString encode( const QStringList &items );
    static QStringList decode( const QString &encoded );
    static QByteArray uriListToByteArray( const UriList &layers );


    friend class TestQgsMimeDataUtils;
};

Q_DECLARE_METATYPE( QgsMimeDataUtils::UriList )

#endif // QGSMIMEDATAUTILS_H
