//  ************************************************************************************************
//
//  BornAgain: simulate and fit reflection and scattering
//
//! @file      GUI/coregui/DataLoaders/AbstractDataLoaderResultModel.h
//! @brief     Defines class AbstractDataLoaderResultModel
//!
//! @homepage  http://www.bornagainproject.org
//! @license   GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2021
//! @authors   Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
//  ************************************************************************************************

#ifndef GUI_COREGUI_DATALOADERS_ABSTRACTDATALOADERRESULTMODEL_H
#define GUI_COREGUI_DATALOADERS_ABSTRACTDATALOADERRESULTMODEL_H

#include <QAbstractItemModel>
#include <QIcon>

//! Base class for result tables of data loaders. Derive from this class and return an instance in
//! YourDataLoader::createResultModel().
//! The result table is the one on the right side when importing CSV files.
class AbstractDataLoaderResultModel : public QAbstractTableModel {
public:
    enum class ColumnType { none, line, fileContent, raw, processed, error };

    AbstractDataLoaderResultModel();

    // overrides of QAbstractTableModel
public:
    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    virtual int rowCount(const QModelIndex& parent) const override;
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
    virtual QVariant headerData(int section, Qt::Orientation orientation,
                                int role = Qt::DisplayRole) const override;

public:
    //! The table header sections which belong to the given column type. Empty if this column type
    //! is not present at all.
    QVector<int> sectionsOfColumnType(ColumnType type) const;

protected:
    //! Returns whether the row given in the index is a skipped row. Only override this for
    //! performance reasons.
    virtual bool rowIsSkipped(const QModelIndex& index) const;

    //! Returns whether the row given in the index contains errors. Only override this for
    //! performance reasons.
    virtual bool rowHasError(const QModelIndex& index) const;

    //! Returns whether the row given in the index is a skipped row. Row counting starts with 0.
    virtual bool rowIsSkipped(int row) const = 0;

    //! Returns whether the row given in the index contains errors. Row counting starts with 0.
    virtual bool rowHasError(int row) const = 0;

    //! Return the table header text for the given column. For convenience, column starts at 0 for
    //! first _calculated_ column, therefore it is not the same as the "real" section in the table
    //! header.
    virtual QString headerTextOfCalculatedColumn(int column) const = 0;

    //! The row count of the result table.
    virtual int rowCount() const = 0;

    //! The number of existing columns related to the given column type. 0 if the type is not
    //! present at all.
    virtual int columnCount(ColumnType type) const = 0;

    //! The text of the given cell. For convenience, column starts at 0 for the given column type,
    //! therefore it is not the same as the "real" section in the table header. This method will not
    //! be called for every row/column present in the table. Instead, optimizations will be done
    //! before calling it. E.g. the calculated values for lines which contain errors will never be
    //! called. Also raw or calculated contents will not be queried if a line is skipped.
    virtual QString cellText(ColumnType type, int row, int column) const = 0;

private:
    //! Calculates the column type of the given index.
    ColumnType columnType(const QModelIndex& index) const;

    //! Calculates the column type of the real header view section.
    ColumnType columnType(int section) const;

    //! Calculates the first real header view section of the given column type.
    //! Returns -1 if the column type does not exist.
    int firstSectionOfColumnType(ColumnType type) const;

    //! Calculates the last real header view section of the given column type.
    //! Returns -1 if the column type does not exist.
    int lastSectionOfColumnType(ColumnType type) const;

private:
    QIcon m_warningIcon;
};

#endif // GUI_COREGUI_DATALOADERS_ABSTRACTDATALOADERRESULTMODEL_H
