//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/View/Scene/MaskGraphicsScene.h
//! @brief     Defines class MaskGraphicsScene.
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifndef BORNAGAIN_GUI_VIEW_SCENE_MASKGRAPHICSSCENE_H
#define BORNAGAIN_GUI_VIEW_SCENE_MASKGRAPHICSSCENE_H

#include "GUI/View/Setup/Canvas2DMode.h"
#include <QGraphicsScene>
#include <map>
#include <memory>

class ColorMap;
class Data2DItem;
class IMaskOverlay;
class IOverlay;
class LineItem;
class MaskGraphicsProxy;
class MaskItem;
class MasksSet;
class OverlayItem;
class PolygonOverlay;
class Viewport;

//! Associated with MaskGraphicsViews, holds ColorMap and masks.

class MaskGraphicsScene : public QGraphicsScene {
    Q_OBJECT
public:
    MaskGraphicsScene();
    ~MaskGraphicsScene() override;

    void switchDataContext(Data2DItem* data_item);
    void updateSize(const QSize& newSize);
    void deleteCurrentItem();
    void cancelCurrentDrawing();

    ColorMap* colorMap() { return m_plot.get(); }

    void connectOverlaySelection(bool isConnected);
    void updateOverlays();

signals:
    void mouseSelectionChanged();
    void itemContextMenuRequest(const QPoint& point, const MaskItem* item);
    void lineItemProcessed();
    void lineItemMoved(const LineItem* sender);
    void lineItemDeleted(const LineItem* sender);
    void switchPanelRequest(int to_panel);

public slots:
    void onActivityChanged(Canvas2DMode::Flag mode);
    void onMaskSetChanged();
    void onProjSetChanged();
    void onSceneSelectionChanged();

private slots:
    void updBoundingRect();
    void onDataDestroyed();

private:
    void mousePressEvent(QGraphicsSceneMouseEvent* event) override;
    void mouseMoveEvent(QGraphicsSceneMouseEvent* event) override;
    void mouseReleaseEvent(QGraphicsSceneMouseEvent* event) override;
    void drawForeground(QPainter* painter, const QRectF& rect) override;
    void contextMenuEvent(QGraphicsSceneContextMenuEvent* event) override;

    void updateCursors();
    void associateItems(Data2DItem* data_item);
    void clearOverlays();
    IOverlay* registerOverlay(OverlayItem* item, bool is_projection);
    void removeOverlay(const OverlayItem* item);

    MasksSet* modelOfMaskItem(const MaskItem* item) const;
    void unselectOtherModelThan(const MasksSet* current_set);
    const MaskItem* maskItemForOverlay(const IOverlay* given_overlay) const;
    const IMaskOverlay* selectedMaskOverlay() const;

    void connectMaskSet(bool isConnected);
    void connectProjSet(bool isConnected);

    void setDrawingInProgress(bool value);

    void selectOnlyItemAtMousePos(QGraphicsSceneMouseEvent* event);
    void selectOnlyGivenItem(QGraphicsItem* givenItem);

    void connectSelectedLineMove(const LineItem* given_line);

    void processRectangleOrEllipseItem(QGraphicsSceneMouseEvent* event);
    void processPolygonItem(QGraphicsSceneMouseEvent* event);
    void processLineItem(QGraphicsSceneMouseEvent* event);
    void processFullframeItem(QGraphicsSceneMouseEvent* event);

    bool isValidMouseClick(QGraphicsSceneMouseEvent* event) const;
    bool isValidForRectangleShapeDrawing(QGraphicsSceneMouseEvent* event) const;
    bool isValidForPolygonDrawing(QGraphicsSceneMouseEvent* event) const;
    bool isValidForLineDrawing(QGraphicsSceneMouseEvent* event) const;
    bool isValidForMaskAllDrawing(QGraphicsSceneMouseEvent* event) const;

    PolygonOverlay* currentPolygon();

    std::unique_ptr<ColorMap> m_plot;
    MaskGraphicsProxy* m_proxy = nullptr;
    Viewport* m_viewport = nullptr;
    MasksSet* m_masks = nullptr;
    MasksSet* m_prjns = nullptr;
    std::map<const OverlayItem*, IOverlay*> m_mask2overlay;
    bool m_mouse_is_pressed = false;
    Data2DItem* m_data_item = nullptr;
    MaskItem* m_active_mask = nullptr;
    QPointF m_mouse_position;
    bool m_drawing_in_progress = false;
    bool m_mask_value = true;
    Canvas2DMode::Flag m_mode;
};

#endif // BORNAGAIN_GUI_VIEW_SCENE_MASKGRAPHICSSCENE_H
