/***************************************************************************
                          qgslabelsearchtree.h
            Node for raster calculator tree
                          --------------------
    begin                : 2010-11-02
    copyright            : (C) 2010 by Marco Hugentobler
    email                : marco dot hugentobler at sourcepole dot ch
***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   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 QGSLABELSEARCHTREE_H
#define QGSLABELSEARCHTREE_H

#include "qgis_core.h"
#include "qgis_sip.h"
#include "qgscalloutposition.h"
#include "qgsgenericspatialindex.h"
#include "qgslabelposition.h"
#include "qgsmapsettings.h"

#include <QList>
#include <QVector>

class QgsPointXY;

#ifndef SIP_RUN
namespace pal
{
  class LabelPosition;
}
#endif

// TODO QGIS 5.0 - this should be private, not exposed to SIP

/**
 * \ingroup core
 * \brief Queries the labeling structure at a given point.
 *
 * This class is a small wrapper around the pal RTree class.
 */
class CORE_EXPORT QgsLabelSearchTree
{
  public:
    QgsLabelSearchTree();
    ~QgsLabelSearchTree();

    QgsLabelSearchTree( const QgsLabelSearchTree &rh ) = delete;
    QgsLabelSearchTree &operator=( const QgsLabelSearchTree &rh ) = delete;

    /**
     * Removes and deletes all the entries.
     * \deprecated QGIS 3.40. Has no effect since QGIS 3.12.
     */
    Q_DECL_DEPRECATED void clear() SIP_DEPRECATED;

    //TODO: why does this break bindings with QList<QgsLabelPosition>?

    /**
     * Returns label position(s) at a given point. QgsLabelSearchTree keeps ownership, don't delete the LabelPositions
     * \note not available in Python bindings
     */
    void label( const QgsPointXY &p, QList<QgsLabelPosition *> &posList ) const SIP_SKIP;

    //TODO: why does this break bindings with QList<QgsLabelPosition>?

    /**
     * Returns a list of all labels generated by the labeling run.
     *
     * \since QGIS 3.20
     */
    QList< QgsLabelPosition > allLabels() const;

    /**
     * Returns label position(s) in given rectangle. QgsLabelSearchTree keeps ownership, don't delete the LabelPositions
     * \note not available in Python bindings
     */
    void labelsInRect( const QgsRectangle &r, QList<QgsLabelPosition *> &posList ) const SIP_SKIP;

    /**
     * Inserts label position. Does not take ownership of labelPos
     * \returns TRUE in case of success
     * \note not available in Python bindings
     */
    bool insertLabel(
      pal::LabelPosition *labelPos,
      QgsFeatureId featureId,
      const QString &layerName,
      const QString &labeltext,
      const QFont &labelfont,
      bool diagram = false,
      bool pinned = false,
      const QString &providerId = QString(),
      bool isUnplaced = false,
      long long linkedId = 0
    ) SIP_SKIP;

    /**
     * Inserts a rendered callout position.
     *
     * \returns TRUE in case of success
     * \note not available in Python bindings
     * \since QGIS 3.20
     */
    bool insertCallout( const QgsCalloutPosition &position ) SIP_SKIP;

    /**
     * Returns the list of callouts with origins or destinations inside the given \a rectangle.
     *
     * The \a rectangle is specified in map coordinates.
     *
     * QgsLabelSearchTree keeps ownership, don't delete the returned objects.
     *
     * \since QGIS 3.20
     */
    QList<const QgsCalloutPosition *> calloutsInRectangle( const QgsRectangle &rectangle ) const;

    /**
     * Returns a list of all label positions sharing the same group ID (i.e. positions for individual characters in a curved label).
     *
     * QgsLabelSearchTree keeps ownership, don't delete the LabelPositions
     *
     * \note not available in Python bindings
     * \since QGIS 3.26
     */
    QList<QgsLabelPosition *> groupedLabelPositions( long long groupId ) const SIP_SKIP;

    /**
     * Sets the map \a settings associated with the labeling run.
     * \since QGIS 3.4.8
     */
    void setMapSettings( const QgsMapSettings &settings );

  private:
    QgsGenericSpatialIndex< QgsLabelPosition > mSpatialIndex;
    long long mNextFeatureId = 1;
    QHash< long long, QList< QgsLabelPosition * > > mLinkedLabelHash;
    std::vector< std::unique_ptr< QgsLabelPosition > > mOwnedPositions;
    QgsGenericSpatialIndex< QgsCalloutPosition > mCalloutIndex;
    std::vector< std::unique_ptr< QgsCalloutPosition > > mOwnedCalloutPositions;
    QgsMapSettings mMapSettings;
    QTransform mTransform;

#ifdef SIP_RUN
    QgsLabelSearchTree( const QgsLabelSearchTree &rh );
    QgsLabelSearchTree &operator=( const QgsLabelSearchTree & );
#endif
};

#endif // QGSLABELTREE_H
