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

#include "GUI/Model/Data/DataItem.h"
#include <utility>

class AmplitudeAxisItem;
class LineItem;
class MasksQModel;
class MasksSet;

class Data2DItem : public DataItem {
    Q_OBJECT
public:
    static constexpr auto M_TYPE{"IntensityData"};

    Data2DItem();
    ~Data2DItem();

    void setDatafield(const Datafield& data) override;

    double xMin() const override;
    double xMax() const override;

    double yMin() const override;
    double yMax() const override;

    double zMin() const;
    double zMax() const;

    //... zoom ranges
    double lowerZ() const;
    double upperZ() const;
    void setZrange(double zmin, double zmax);
    void copyZRangeFromItem(DataItem* sourceItem);
    bool isZoomed() const;

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

    //... enable/disable colormap interpolation
    bool isInterpolated() const { return m_is_interpolated; }
    void setInterpolated(bool interp);

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

    void updateDataRange();
    void computeDataRange();
    std::pair<double, double> dataRange() const;

    const AmplitudeAxisItem* zAxisItem() const { return m_z_axis.get(); }
    AmplitudeAxisItem* zAxisItem() { return m_z_axis.get(); }

    MasksSet* masksRW() { return m_masks.get(); }
    const MasksSet* masks() const { return m_masks.get(); }

    MasksSet* prjnsRW() { return m_prjns.get(); }
    const MasksSet* prjns() const { return m_prjns.get(); }

    size_t rank() const override { return 2; }
    size_t axdim(int i) const override;

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

    void setAxesRangeToData(); //!< Sets zoom range of x,y axes to axes of input data

    // write/read

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

signals:
    void interpolationChanged(bool isInterpol);
    void projectionCreated();
    void projectionPositionChanged(const LineItem* projection);
    void projectionGone(const LineItem* projection);

private:
    void updateAxesZoomLevel();

    bool m_is_interpolated;
    std::unique_ptr<AmplitudeAxisItem> m_z_axis;
    std::unique_ptr<MasksSet> m_masks;
    std::unique_ptr<MasksSet> m_prjns;
};

#endif // BORNAGAIN_GUI_MODEL_DATA_DATA2DITEM_H
