#ifndef TABLESTABLEMODEL_H
#define TABLESTABLEMODEL_H

//#include "catalog/models/BaseTableModel.h"
#include "ui/catalog/tables/TableNode.h"
#include "ui/catalog/tables/TableSize.h"
#include "NamespaceFilter.h"
#include "catalog/PgClass.h"
#include <QAbstractItemModel>
#include <memory>
#include <vector>

class OpenDatabase;
class PgClass;
class PgDatabaseCatalog;

class TablesTableModel: public QAbstractItemModel {
public:
    using RowItem = PgClass;
	enum e_Columns : int {
		NameCol, ///< either table, ns.table or table (ns) depending on settings/filters
		NamespaceCol,
		KindCol,
		OwnerCol,
		TablespaceCol,
		OptionsCol,
		AclCol,
        CommentCol,
        TotalSizeCol,
        TableSizeCol,
        IndexSizeCol,
        ToastSizeCol,

		colCount };

    TablesTableModel(std::shared_ptr<OpenDatabase> opendatabase, QObject *parent);

	void setNamespaceFilter(NamespaceFilter nsf);
	void setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat);

	QVariant headerData(int section, Qt::Orientation orientation, int role) const override;

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

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

    QModelIndex parent(const QModelIndex &index) const override;

    QVariant data(const QModelIndex &index, int role) const override;

    RowItem rowItem(const QModelIndex &index) const
    {
        return nodeFromIndex(index)->_class;
    }

    static const TableNode* nodeFromIndex(const QModelIndex &index);

private:

    using TableSizes = std::vector<TableSize>;

    // this is a readonly model so when the vectors have been filled
    // they will not change anymore and it is safe to assume the indexes
    // of elements do not change

	std::shared_ptr<const PgDatabaseCatalog> m_catalog;
	NamespaceFilter m_namespaceFilter = NamespaceFilter::User;
    std::shared_ptr<TableNode> rootNode;
	QMetaObject::Connection refreshConnection;
    std::shared_ptr<OpenDatabase> openDatabase;


	Oid getType(int column) const;
	QVariant getData(const QModelIndex &index) const;

    using OidClassIndex = std::map<Oid, std::shared_ptr<TableNode>>;

    void StartLoadTableSizes(OidClassIndex oidIndex);
    TableSizes QueryTableSizes() const;
    void PopulateSizes(
        const OidClassIndex &oidIndex,
        const std::vector<TableSize> &sizes
    );


    std::function<bool(const PgClass&)> GetNamespaceFilterLambda();
private slots:
	void refresh();

};

#endif // TABLESTABLEMODEL_H
