//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/Model/Data/IntensityDataItem.h
//! @brief     Defines class IntensityDataItem
//!
//! @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_MODEL_DATA_INTENSITYDATAITEM_H
#define BORNAGAIN_GUI_MODEL_DATA_INTENSITYDATAITEM_H

#include "GUI/Model/Data/DataItem.h"

class AmplitudeAxisItem;
class MaskContainerItem;
class MaskItemObject;
class ProjectionContainerItem;
class QCPColorGradient;

class IntensityDataItem : public DataItem {
    Q_OBJECT

public:
    static constexpr auto M_TYPE{"IntensityData"};

    IntensityDataItem();
    ~IntensityDataItem();

    void setDatafield(Datafield* data) override;

    // Returns min and max range of x-axis as given by IntensityData
    double xMin() const override;
    double xMax() const override;

    // Returns min and max range of y-axis as given by IntensityData
    double yMin() const override;
    double yMax() const override;

    // Returns min and max range of y-axis as given by IntensityData
    double zMin() const;
    double zMax() const;

    // Lower and upper zoom ranges of z-axis
    double lowerZ() const;
    double upperZ() const;
    void setLowerZ(double zmin);
    void setUpperZ(double zmax);
    void setLowerAndUpperZ(double zmin, double zmax);
    void copyZRangeFromItem(DataItem* sourceItem);

    //! Color scheme of the color map
    QCPColorGradient currentGradientQCP() const;
    QString currentGradient() const;
    void setCurrentGradient(const QString& gradient);
    ComboProperty gradientCombo() const;

    // Logarithmic Z scale
    bool isLog() const;
    void setLog(bool islog);

    // Enable/disable colormap interpolation
    bool isInterpolated() const;
    void setInterpolated(bool interp);

    // True if min, max range of Z-axis is locked (change not allowed)
    bool isZaxisLocked() const;
    void setZaxisLocked(bool state);

    void updateDataRange();
    void computeDataRange();
    QPair<double, double> dataRange() const;

    const AmplitudeAxisItem* zAxisItem() const;
    AmplitudeAxisItem* zAxisItem();

    MaskContainerItem* maskContainerItem();
    const MaskContainerItem* maskContainerItem() const;
    MaskContainerItem* getOrCreateMaskContainerItem();

    ProjectionContainerItem* projectionContainerItem();
    const ProjectionContainerItem* projectionContainerItem() const;
    ProjectionContainerItem* getOrCreateProjectionContainerItem();

    bool hasMasks() const;
    bool hasProjections() const;

    //! Updates data on the change of axes units
    void updateCoords(const ICoordSystem& converter) override;

    //! Returns dimensions and axesbins of data
    std::vector<int> shape() const override;

    //! Set axes viewport to original data.
    void resetView() override;

    // write/read

    void writeTo(QXmlStreamWriter* w) const override;
    void readFrom(QXmlStreamReader* r) override;

signals:
    void gradientChanged();
    void interpolationChanged(bool isInterpol);
    void projectionCreated();
    void projectionPositionChanged(MaskItemObject* projection);
    void projectionGone(MaskItemObject* projection);
    void alignRanges();

private:
    void updateAxesZoomLevel();
    void updateAxesLabels();

    bool m_isInterpolated;
    ComboProperty m_gradient;
    std::unique_ptr<AmplitudeAxisItem> m_zAxis;
    std::unique_ptr<MaskContainerItem> m_maskContainerItem;
    std::unique_ptr<ProjectionContainerItem> m_projectionContainerItem;
};

#endif // BORNAGAIN_GUI_MODEL_DATA_INTENSITYDATAITEM_H
