/***************************************************************************
    qgsvectorwarper.h
     --------------------------------------
    Date                 : February 2022
    Copyright            : (C) 2022 by Nyall Dawson
    Email                : nyall dot dawson 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 QGSVECTORWARPER_H
#define QGSVECTORWARPER_H

#include "qgis_analysis.h"
#include "qgis_sip.h"
#include "qgsgcptransformer.h"
#include "qgsgcppoint.h"
#include "qgsfeatureiterator.h"
#include "qgstaskmanager.h"
#include "qgsvectorlayerfeatureiterator.h"

class QgsFeatureSink;

/**
 * \ingroup analysis
 * \brief Vector layer warper which warps vector layers based on a list of source and destination GCPs.
 *
 * \since QGIS 3.26
*/
class ANALYSIS_EXPORT QgsVectorWarper
{
  public:
    /**
     * Constructor for QgsVectorWarper.
     *
     * \param method specifies the transformation method
     * \param points list of GCP points to use for the transformation
     * \param destinationCrs target CRS for transformed features
     */
    explicit QgsVectorWarper( QgsGcpTransformerInterface::TransformMethod method, const QList<QgsGcpPoint> &points, const QgsCoordinateReferenceSystem &destinationCrs );

    /**
     * Transforms the features from \a iterator and adds the results to the specified \a sink.
     *
     * The optional \a feedback argument can be used for progress reporting and cancellation.
     *
     * \returns TRUE if all features were successfully transformed
     */
    bool transformFeatures( QgsFeatureIterator &iterator, QgsFeatureSink *sink, const QgsCoordinateTransformContext &context, QgsFeedback *feedback = nullptr ) const;

    /**
     * Returns the last error obtained during transformation.
     */
    QString error() const { return mError; }

  private:
    QgsGcpTransformerInterface::TransformMethod mMethod = QgsGcpTransformerInterface::TransformMethod::Linear;
    QList<QgsGcpPoint> mPoints;
    QgsCoordinateReferenceSystem mDestinationCrs;

    mutable QString mError;
};


/**
 * \ingroup analysis
 * \brief A task for warping a vector layer in a background thread.
 *
 * \since QGIS 3.26
*/
class ANALYSIS_EXPORT QgsVectorWarperTask : public QgsTask
{
    Q_OBJECT

  public:
    /**
     * Constructor for QgsVectorWarperTask.
     *
     * \param method transformation method
     * \param points GCP point list
     * \param destinationCrs destination layer CRS
     * \param layer source layer
     * \param fileName filename for destination layer
     */
    QgsVectorWarperTask( QgsGcpTransformerInterface::TransformMethod method, const QList<QgsGcpPoint> &points, const QgsCoordinateReferenceSystem &destinationCrs, QgsVectorLayer *layer, const QString &fileName );

    void cancel() override;

    //! Task results
    enum class Result
    {
      Success,  //!< Warping completed successfully
      Canceled, //!< Task was canceled before completion
      Error,    //!< An error occurred while warping
    };

    /**
     * Returns the result of running the task.
     */
    Result result() const { return mResult; }

    /**
     * Returns the descriptive error message, if an error occurred.
     */
    QString errorMessage() const { return mErrorMessage; }

  protected:
    bool run() override;

  private:
    QgsGcpTransformerInterface::TransformMethod mMethod = QgsGcpTransformerInterface::TransformMethod::Linear;
    long long mFeatureCount = 0;
    std::unique_ptr<QgsVectorLayerFeatureSource> mSource;
    QList<QgsGcpPoint> mPoints;
    QgsCoordinateReferenceSystem mDestinationCrs;

    QString mDestFileName;

    std::unique_ptr<QgsFeedback> mFeedback;

    QgsCoordinateTransformContext mTransformContext;
    QgsFields mFields;
    Qgis::WkbType mWkbType = Qgis::WkbType::Unknown;

    Result mResult = Result::Success;
    QString mErrorMessage;
    double mLastProgress = 0;
};


#endif //QGSVECTORWARPER_H
