/***************************** LICENSE START ***********************************

 Copyright 2015 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#pragma once

#include <QGraphicsItem>
#include <QGraphicsView>
#include <QPen>
#include <QBrush>

class QGraphicsScene;

class MvQEdgeItem;
class MvQProfileItem;
class MvQProfileView;

class MvProfileData;
class MvProfileChange;

class MvQNodeItem : public QGraphicsItem
{
public:
    MvQNodeItem(MvQProfileItem*, bool, float);
    ~MvQNodeItem();

    void addEdge(MvQEdgeItem*);
    QRectF boundingRect() const;
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);
    void setYPos(float y) { yPos_ = y; }
    bool editable() const { return editable_; }

protected:
    QVariant itemChange(GraphicsItemChange, const QVariant&);
    void mousePressEvent(QGraphicsSceneMouseEvent*);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent*);
    void mouseMoveEvent(QGraphicsSceneMouseEvent*);
    void hoverEnterEvent(QGraphicsSceneHoverEvent*);
    void hoverLeaveEvent(QGraphicsSceneHoverEvent*);

private:
    MvQProfileItem* prof_;
    bool editable_;
    float yPos_;
    QList<MvQEdgeItem*> edges_;

    QBrush brush_;
    QBrush idleBrush_;
    QBrush hoverBrush_;
    QBrush moveBrush_;

    QPen pen_;
    QPen idlePen_;
    QPen hoverPen_;
    QPen movePen_;

    int size_;
    int idleSize_;
    int moveSize_;
    int hoverSize_;
};

class MvQEdgeItem : public QGraphicsItem
{
public:
    MvQEdgeItem(MvQNodeItem*, MvQNodeItem*);

    void adjust();
    QRectF boundingRect() const;
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*);

private:
    MvQNodeItem* fromNode_;
    MvQNodeItem* toNode_;
    QPointF fromPoint_;
    QPointF toPoint_;
    QPen pen_;
};

class MvQProfileItem : public QGraphicsItem
{
    friend class MvQNodeItem;

public:
    MvQProfileItem(MvQProfileView*, MvProfileData*, bool, int, int, int, QSize, bool, float, float);
    ~MvQProfileItem();

    QRectF boundingRect() const;
    void paint(QPainter*, const QStyleOptionGraphicsItem*,
               QWidget* widget = 0);

    bool updateValue(const MvProfileChange&);
    void setStep(int);
    void adjustSize(QSize);
    void adjustSize(QRectF);
    void setLevelRange(int, int);
    void setLevelRange(int, int, float, float);
    void setValueRange(float, float);
    void valueRange(int, int, float&, float&);
    void valueRange(float&, float&);
    void setEditRadius(int);
    void reload();
    QRectF frameRect() const { return frameRect_; }
    void setSubPlot(bool b) { subPlot_ = b; }
    int levelNum() { return lastIndex_ - firstIndex_ + 1; }
    bool cursorData(QPointF, QString&);
    int firstIndex() const { return firstIndex_; }
    int lastIndex() const { return lastIndex_; }

protected:
    void initFrame(QSize);
    void initFrame(QRectF);
    void adjustFrame();
    void adjustData();
    void nodeMoved(MvQNodeItem*);
    void checkValueRange();

    MvQProfileView* view_;
    MvProfileData* data_;

    QRectF frameRect_;
    QRectF bRect_;

    float xRatio_;
    float yRatio_;
    float frameXMin_;
    float frameXMax_;
    float tickXStep_;
    float tickXLabelStep_;
    int tickXLabelStepOffset_;
    int step_;
    bool zeroLine_;
    QList<MvQNodeItem*> nodes_;
    QList<MvQEdgeItem*> edges_;

    int minXSize_;
    int minYSize_;
    bool editable_;
    int editRadius_;
    int firstIndex_;
    int lastIndex_;
    bool subPlot_;
    bool presetMinMax_;
    float presetMin_;
    float presetMax_;
    QPen pen_;
    QPen gridPen_;
    QBrush outsideBrush_;
    QBrush sceneBgBrush_;
    QColor editableColour_;
    QColor standardColour_;
};

class MvQProfileView : public QGraphicsView
{
    friend class MvQProfileItem;

    Q_OBJECT

public:
    MvQProfileView(QWidget* parent = 0);

    void setProfile(QList<MvProfileData*>, bool, int, int);
    void update(const MvProfileChange&);
    void reload();
    void setLevelRange(int, int);
    void setEditRadius(int);

signals:
    void cursorData(QString);

protected:
    void resizeEvent(QResizeEvent*);
    void adjustSize();
    void adjustValueRange();
    void mouseMoveEvent(QMouseEvent*);

    QGraphicsScene* scene_;
    QList<MvQProfileItem*> prof_;
};
