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

 Copyright 2012 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 "MvQFeatureCurveItem.h"

//-----------------------------------------------------------
// The points of a Curve object
//-----------------------------------------------------------
class MvQFeatureMetCurveItem : public MvQFeatureCurveItem
{
public:
    double halo() const override;
    void flipSymbolDirection() override;

    const std::string& frontSubType() const override { return front_type_; }
    void setFrontSubType(const std::string&) override;

    bool canBeCreatedOutOfView() const override { return false; }
    bool canBePastedOutOfView() const override { return true; }

protected:
    MvQFeatureMetCurveItem(WsType* feature);
    void buildShape() override;
    bool getRequestParameters() override;
    virtual bool getSimpleRequestParameters();

    virtual void paint_normal(QPainter*);
    virtual void paint_fronto(QPainter*);
    void init_line_segment();
    bool compute_next_line_segment(QPointF&, QPointF&, float, float);
    virtual void makeSymbol(const QPointF&, const QPointF&, QVector<QPointF>&) {}
    void makeTriangle(const QPointF&, const QPointF&, float, bool, QVector<QPointF>&);
    QSizeF makeSemiCircle(float, float, float, QVector<QPointF>&);
    QSizeF makeCircle(float, float, float, QVector<QPointF>&);
    void makeHalfCircle(const QPointF&, const QPointF&, bool has_offset, QVector<QPointF>&);
    QSizeF makeCross(float, QVector<QPointF>&);
    void paintSeparator(QPainter*, QPen&, QBrush&, const QPointF&, const QPointF&);
    void paintSeparatorPolygon(QPainter*, QBrush&, const QPointF&, const QPointF&);
    void paintSeparatorPolygon2(QPainter*, QBrush&, const QPointF&, const QPointF&);
    void paintSeparatorLine(QPainter*, QPen&, const QPointF&, const QPointF&);
    void paintLineSegment(QPainter*, int, int, const QPointF&, const QPointF&);
    void rotateSymbol(const QPointF&, const QPointF&, bool, QVector<QPointF>&);
    void translateSymbol(const QPointF&, const QPointF&, QVector<QPointF>&);
    void translateSymbol(const QPointF&, QVector<QPointF>&);
    void translateSymbol(const QPointF&, const QPointF&, QVector<QPointF>&, QVector<QPointF>&);
    void linearInterpolation(int, float, QPointF&);

    std::string front_type_;
    bool type_normal_{true};

    bool symbolFacesLeft_{true};
    float symbolGap_{0.};         // pixels
    QVector<QPointF> symbolSep_;  // symbol separator

    int ind_{0};          // curve index
    int startIndex_{-1};  // line segment starting index
    int endIndex_{-1};    // line segment ending index
};


//-----------------------------------------------------------------
// The Cold Front class
//-----------------------------------------------------------------
class MvQFeatureColdFrontItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureColdFrontItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    void updateSymbols() override;
    void makeSymbol(const QPointF&, const QPointF&,
                    QVector<QPointF>&) override;
};

//-----------------------------------------------------------------
// The Warm Front class
//-----------------------------------------------------------------
class MvQFeatureWarmFrontItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureWarmFrontItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    void updateSymbols() override;
    void makeSymbol(const QPointF&, const QPointF&,
                    QVector<QPointF>&) override;
};

//-----------------------------------------------------------------
// The Occluded Front class
//-----------------------------------------------------------------
class MvQFeatureOccludedItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureOccludedItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
    void paint_normal(QPainter*) override;
    void paint_fronto(QPainter*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    void updateSymbols() override;
};

//-----------------------------------------------------------------
// The Quasi Stationary Front class
//-----------------------------------------------------------------
class MvQFeatureQuasiStationaryItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureQuasiStationaryItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
    void paint_normal(QPainter*) override;
    void paint_fronto(QPainter*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override;
    void updateSymbols() override;

    std::vector<bool> symbTag_;
    QVector<QPointF> symbSc_;  // symbol semi-circle
    QVector<QPointF> symbTr_;  // symbol triangle

    QPen linePenTr_;
    QBrush symbolBrushTr_;
    QPen linePenSc_;
    QBrush symbolBrushSc_;
};

//-----------------------------------------------------------------
// The Ridge Front class
//-----------------------------------------------------------------
class MvQFeatureRidgeItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureRidgeItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    MvQFeatureRidgeItem(WsType* feature);
    bool getRequestParameters() override;
    void updateSymbols() override;
};


//-----------------------------------------------------------------
// The Intertropical Discontinuity class
//-----------------------------------------------------------------
class MvQFeatureIttDiscontinuityItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureIttDiscontinuityItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override;

    QPen linePenC1_;
    QPen linePenC2_;
};

//-----------------------------------------------------------------
// The Convergence Line Front class
//-----------------------------------------------------------------
class MvQFeatureConvergenceLineItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureConvergenceLineItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override;
    void updateSymbols() override;
};

//-----------------------------------------------------------------
// The Instability and Shear Line Front parent class
//-----------------------------------------------------------------
class MvQFeatureInstabilityShearLineItem : public MvQFeatureMetCurveItem
{
public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;

protected:
    MvQFeatureInstabilityShearLineItem(WsType* feature, bool bShear);
    bool getRequestParameters() override;
    void updateSymbols() override;

    bool bShear_{true};
    double diameter_{10};
};

//-----------------------------------------------------------------
// The Instability Line Front class
//-----------------------------------------------------------------
class MvQFeatureInstabilityLineItem : public MvQFeatureInstabilityShearLineItem
{
    friend class MvQFeatureMaker<MvQFeatureInstabilityLineItem>;

protected:
    MvQFeatureInstabilityLineItem(WsType* feature);
};

//-----------------------------------------------------------------
// The Shear Line Front class
//-----------------------------------------------------------------
class MvQFeatureShearLineItem : public MvQFeatureInstabilityShearLineItem
{
    friend class MvQFeatureMaker<MvQFeatureShearLineItem>;

protected:
    MvQFeatureShearLineItem(WsType* feature);
};

//-----------------------------------------------------------------
// The Tropical Wave class
//-----------------------------------------------------------------
class MvQFeatureTropicalWaveItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureTropicalWaveItem>;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override
    {
        return getSimpleRequestParameters();
    }

    void updateSymbols() override {}
};

//-----------------------------------------------------------------
// The Intertropical Convergence Zone class
//-----------------------------------------------------------------
class MvQFeatureItczItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureItczItem>;

public:
    void paint(QPainter*, const QStyleOptionGraphicsItem*, QWidget*) override;
    bool neighbourPoints(const QVector<QPointF>&, int&, float, float);
    bool drawInBetweenLine(QPainter*, const QVector<QPointF>&,
                           const QVector<QPointF>&,
                           const QPointF&, const QPointF&, float, int&, int&);

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override;
    void updateSymbols() override;
    void buildShape() override;

    int thickness_{1};
    int width_{10};
    int intensity_{1};
    int intensityGap_{10};
};

//-----------------------------------------------------------------
// The Trough class
//-----------------------------------------------------------------
class MvQFeatureTroughItem : public MvQFeatureMetCurveItem
{
    friend class MvQFeatureMaker<MvQFeatureTroughItem>;

protected:
    using MvQFeatureMetCurveItem::MvQFeatureMetCurveItem;
    bool getRequestParameters() override
    {
        return getSimpleRequestParameters();
    }

    void updateSymbols() override {}
};
