// SPDX-License-Identifier: LGPL-2.1-or-later
//
// SPDX-FileCopyrightText: 2009 Andrew Manson <g.real.ate@gmail.com>
// SPDX-FileCopyrightText: 2013 Thibaut Gridel <tgridel@free.fr>
// SPDX-FileCopyrightText: 2014 Calin Cruceru <crucerucalincristian@gmail.com>
//

#ifndef MARBLE_ANNOTATEPLUGIN_H
#define MARBLE_ANNOTATEPLUGIN_H

#include "GeoDataGroundOverlay.h"
#include "GroundOverlayFrame.h"
#include "RenderPlugin.h"
#include "SceneGraphicsItem.h"

#include <QMenu>
#include <QSortFilterProxyModel>

namespace Marble
{

class MarbleWidget;
class GeoDataDocument;
class GeoDataLinearRing;
class AreaAnnotation;
class PolylineAnnotation;
class PlacemarkTextAnnotation;
class OsmPlacemarkData;

/**
 * @brief This class specifies the Marble layer interface of a plugin which
 * annotates maps with polygons and placemarks.
 */
class AnnotatePlugin : public RenderPlugin
{
    Q_OBJECT
    Q_PLUGIN_METADATA(IID "org.kde.marble.AnnotatePlugin")
    Q_INTERFACES(Marble::RenderPluginInterface)
    MARBLE_PLUGIN(AnnotatePlugin)

public:
    explicit AnnotatePlugin(const MarbleModel *model = nullptr);
    ~AnnotatePlugin() override;

    QStringList backendTypes() const override;

    QString renderPolicy() const override;

    QStringList renderPosition() const override;

    QString name() const override;

    QString guiString() const override;

    QString nameId() const override;

    QString version() const override;

    QString description() const override;

    QIcon icon() const override;

    QString copyrightYears() const override;

    QList<PluginAuthor> pluginAuthors() const override;

    void initialize() override;

    bool isInitialized() const override;

    QString runtimeTrace() const override;

    const QList<QActionGroup *> *actionGroups() const override;

    bool render(GeoPainter *painter, ViewportParams *viewport, const QString &renderPos, GeoSceneLayer *layer = nullptr) override;

Q_SIGNALS:
    void placemarkMoved();
    void nodeAdded(const GeoDataCoordinates &coordinates);
    void itemMoved(GeoDataPlacemark *placemark);
    void mouseMoveGeoPosition(const QString &);

private Q_SLOTS:
    void enableModel(bool enabled);
    void askToRemoveFocusItem();
    void removeFocusItem();
    void clearAnnotations();
    void saveAnnotationFile();
    void loadAnnotationFile();
    void openAnnotationFile(const QString &);
    void copyItem();
    void cutItem();
    void pasteItem();

    void addTextAnnotation();
    void editTextAnnotation();
    void stopEditingTextAnnotation(int result);

    void addOverlay();
    void editOverlay();
    void removeOverlay();
    void updateOverlayFrame(GeoDataGroundOverlay *overlay);

    void addPolygon();
    void stopEditingPolygon(int result);
    void setAddingPolygonHole(bool enabled);
    void setAddingNodes(bool enabled);
    void editPolygon();
    void selectNode();
    void deleteNode();
    void deselectNodes();
    void deleteSelectedNodes();
    void setAreaAvailable();

    void addPolyline();
    void editPolyline();
    void stopEditingPolyline(int result);
    void setPolylineAvailable();

    void addRelation(const OsmPlacemarkData &relationOsmData);
    void downloadOsm();

protected:
    bool eventFilter(QObject *watched, QEvent *event) override;

private:
    void addContextItems();
    void setupActions(MarbleWidget *marbleWidget);
    static void disableActions(QActionGroup *group);
    static void enableAllActions(QActionGroup *group);
    void enableActionsOnItemType(const QString &type);
    void disableFocusActions();

    void setupTextAnnotationRmbMenu();
    void showTextAnnotationRmbMenu(qreal x, qreal y);

    void setupGroundOverlayModel();
    void setupOverlayRmbMenu();
    void showOverlayRmbMenu(GeoDataGroundOverlay *overlay, qreal x, qreal y);
    void displayOverlayFrame(GeoDataGroundOverlay *overlay);
    void clearOverlayFrames();

    void setupPolygonRmbMenu();
    void setupNodeRmbMenu();
    void showPolygonRmbMenu(qreal x, qreal y);
    void showNodeRmbMenu(qreal x, qreal y);

    void setupPolylineRmbMenu();
    void showPolylineRmbMenu(qreal x, qreal y);

    void handleUncaughtEvents(QMouseEvent *mouseEvent);
    void handleReleaseOverlay(QMouseEvent *mouseEvent);
    bool handleDrawingPolyline(QMouseEvent *mouseEvent);
    bool handleDrawingPolygon(QMouseEvent *mouseEvent);
    bool handleMovingSelectedItem(QMouseEvent *mouseEvent);

    void handleRequests(QMouseEvent *mouseEvent, SceneGraphicsItem *item);
    void handleSuccessfulPressEvent(QMouseEvent *mouseEvent, SceneGraphicsItem *item);
    void handleSuccessfulHoverEvent(QMouseEvent *mouseEvent, SceneGraphicsItem *item);
    void handleSuccessfulReleaseEvent(QMouseEvent *mouseEvent, SceneGraphicsItem *item);

    void announceStateChanged(SceneGraphicsItem::ActionState newState);
    void setupCursor(SceneGraphicsItem *item);

    const GeoDataCoordinates mouseGeoDataCoordinates(QMouseEvent *mouseEvent) const;

    bool m_isInitialized;
    bool m_widgetInitialized;
    MarbleWidget *m_marbleWidget;

    QMenu *m_overlayRmbMenu;
    QMenu *m_polygonRmbMenu;
    QMenu *m_nodeRmbMenu;
    QMenu *m_textAnnotationRmbMenu;
    QMenu *m_polylineRmbMenu;

    QList<QActionGroup *> m_actions;
    QSortFilterProxyModel m_groundOverlayModel;
    QMap<GeoDataGroundOverlay *, SceneGraphicsItem *> m_groundOverlayFrames;

    // A list of all osm relations
    QHash<qint64, OsmPlacemarkData> m_osmRelations;

    GeoDataDocument *m_annotationDocument;
    QList<SceneGraphicsItem *> m_graphicsItems;

    SceneGraphicsItem *m_movedItem;
    SceneGraphicsItem *m_focusItem;
    SceneGraphicsItem *m_editedItem;
    GeoDataGroundOverlay *m_rmbOverlay;

    GeoDataPlacemark *m_polylinePlacemark;
    GeoDataPlacemark *m_polygonPlacemark;

    GeoDataCoordinates m_fromWhereToCopy;
    SceneGraphicsItem *m_clipboardItem;
    QAction *m_pasteGraphicItem;

    bool m_drawingPolygon;
    bool m_drawingPolyline;
    bool m_addingPlacemark;
    bool m_editingDialogIsShown;
};

}

#endif // MARBLE_ANNOTATEPLUGIN_H
