/***************************** 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 <QAbstractItemModel>

#include "GribMetaData.h"

class GribItem;
class GribMvDump;
class GribStdDump;
class GribWmoDump;
class GribValueDump;

class MvQGribMvDumpModel : public QAbstractItemModel
{
public:
    using QAbstractItemModel::QAbstractItemModel;
    ~MvQGribMvDumpModel() override;

    int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const override;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const override;

    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex&) const override;

    void setDumpData(GribMvDump*);
    GribMvDump* dumpData() const { return data_; }
    bool hasData() const { return data_ != nullptr; }
    void clear();
    void setGribNameSpace(QString);
    void setFilter(QString);

    Qt::ItemFlags flags(const QModelIndex&) const override;
    Qt::DropActions supportedDropActions() const override;
    QStringList mimeTypes() const override;
    QMimeData* mimeData(const QModelIndexList&) const override;
    bool dropMimeData(const QMimeData* data,
                      Qt::DropAction action, int row, int column,
                      const QModelIndex& parent) override;

private:
    enum Column
    {
        KeyColum = 0,
        TypeColumn = 1,
        ValueColumn = 2,
        StrValueColumn = 3
    };
    QString label(GribItem*, const int) const;
    GribMvDump* data_{nullptr};
    QString gribNameSpace_;
    QString filter_;
};

class MvQGribWmoDumpModel : public QAbstractItemModel
{
public:
    using QAbstractItemModel::QAbstractItemModel;
    ~MvQGribWmoDumpModel() override;

    int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const override;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const override;

    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex&) const override;

    void setDumpData(GribWmoDump*);
    GribWmoDump* dumpData() const { return data_; }
    bool hasData() const { return data_ != nullptr; }
    void clear();

    Qt::ItemFlags flags(const QModelIndex&) const override;
    Qt::DropActions supportedDropActions() const override;
    QStringList mimeTypes() const override;
    QMimeData* mimeData(const QModelIndexList&) const override;
    bool dropMimeData(const QMimeData* data,
                      Qt::DropAction action, int row, int column,
                      const QModelIndex& parent) override;

private:
    QString label(GribSection*, const int) const;
    QString label(GribItem*, const int) const;
    QString label(QString, const int) const;
    int idToLevel(int) const;
    int idToParentRow(int) const;
    int idToGrandParentRow(int) const;
    enum Column
    {
        PositionColum = 0,
        KeyColumn = 1,
        ValueColumn = 2
    };

    GribWmoDump* data_{nullptr};
};

class MvQGribStdDumpModel : public QAbstractItemModel
{
public:
    using QAbstractItemModel::QAbstractItemModel;
    ~MvQGribStdDumpModel() override;

    int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const override;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const override;

    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex&) const override;

    void setDumpData(GribStdDump*);
    GribStdDump* dumpData() const { return data_; }
    bool hasData() const { return data_ != nullptr; }
    void clear();

    Qt::ItemFlags flags(const QModelIndex&) const override;
    Qt::DropActions supportedDropActions() const override;
    QStringList mimeTypes() const override;
    QMimeData* mimeData(const QModelIndexList&) const override;
    bool dropMimeData(const QMimeData* data,
                      Qt::DropAction action, int row, int column,
                      const QModelIndex& parent) override;

private:
    QString label(GribItem*, const int) const;
    QString label(std::string, const int) const;
    int idToLevel(int) const;
    int idToParentRow(int) const;
    enum Column
    {
        KeyColum = 0,
        ValueColumn = 1,
        DescColumn = 2
    };

    GribStdDump* data_{nullptr};
};

class MvQGribValueDumpModel : public QAbstractItemModel
{
public:
    using QAbstractItemModel::QAbstractItemModel;
    ~MvQGribValueDumpModel() override;

    int columnCount(const QModelIndex& parent = QModelIndex()) const override;
    int rowCount(const QModelIndex& parent = QModelIndex()) const override;

    QVariant data(const QModelIndex&, int role = Qt::DisplayRole) const override;
    QVariant headerData(int, Qt::Orientation, int role = Qt::DisplayRole) const override;

    QModelIndex index(int, int, const QModelIndex& parent = QModelIndex()) const override;
    QModelIndex parent(const QModelIndex&) const override;

    void setDumpData(GribValueDump*);
    GribValueDump* dumpData() const { return data_; }
    void clear();

private:
    GribValueDump* data_{nullptr};
    double minValAsDecimal_{0.001};
};
