// Copyright 2021 Filippo Rusconi
// GPLv3+

#pragma once

/////////////////////// StdLib includes
#include <vector>
#include <limits>

/////////////////////// Qt includes
#include <QString>
#include <QPointF>


/////////////////////// Local includes
#include "pappsomspp/export-import-config.h"
#include "../../types.h"
#include "integrationscopebase.h"

namespace pappso
{

// This class represents the case where the user draws a line in a trace plot
// widget, with the aim of integrating data in single-dimension manner (over a
// range in the X axis). Having no height, this IntegrationScope is like a line.

/* Like this:

P---------------------------+

|--------- m_width ---------|

With P the m_point.

 */

class PMSPP_LIB_DECL IntegrationScope : public IntegrationScopeBase
{
    Q_PROPERTY(QPointF point READ getPoint() WRITE setPoint() NOTIFY pointChanged() FINAL)
    Q_PROPERTY(double width READ getWidth() WRITE setWidth() NOTIFY widthChanged() FINAL)
public:
    IntegrationScope(QObject *parent_p = nullptr);
    IntegrationScope(const QPointF &point, double width, QObject *parent_p = nullptr);
    IntegrationScope(const QPointF &point,
                     double width,
                     Enums::DataKind data_kind,
                     QObject *parent_p = nullptr);
    IntegrationScope(const IntegrationScope &other, QObject *parent_p = nullptr);

    virtual ~IntegrationScope();

    virtual IntegrationScope &operator=(const IntegrationScope &other);

    virtual void setPoint(const QPointF &point);
    virtual bool getPoint(QPointF &point) const override;

    virtual IntegrationScopeFeatures getLeftMostPoint(QPointF &point) const override;
    virtual IntegrationScopeFeatures getRightMostPoint(QPointF &point) const override;

    virtual IntegrationScopeFeatures getTopMostPoint(QPointF &point) const override;
    virtual IntegrationScopeFeatures getBottomMostPoint(QPointF &point) const override;

    virtual void setWidth(double width);
    virtual IntegrationScopeFeatures getWidth(double &width) const override;

    virtual bool range(Enums::Axis axis, double &start, double &end) const override;

    virtual void setDataKindX(Enums::DataKind data_kind) override;
    virtual bool getDataKindX(Enums::DataKind &data_kind) override;

    bool is1D() const override;
    bool is2D() const override;

    virtual bool isRectangle() const override;
    virtual bool isRhomboid() const override;

    virtual bool transpose() override;

    virtual void update(const QPointF &point, double width);

    virtual bool contains(const QPointF &point) const override;

    virtual QString toString() const override;

    virtual void reset() override;

signals:
    void pointChanged();
    void widthChanged();

protected:
    QPointF m_point;
    double m_width;
    Enums::DataKind m_dataKindX = Enums::DataKind::unset;
};

typedef std::shared_ptr<IntegrationScope> IntegrationScopeSPtr;
typedef std::shared_ptr<const IntegrationScope> IntegrationScopeCstSPtr;

} // namespace pappso
