#pragma once

#include <QTableWidget>
#include <QTreeView>
#include <QSortFilterProxyModel>
#include "util/PgLabItemDelegate.h"
#include "util/PgLabTableView.h"
#include <optional>

class PgDatabaseCatalog;

template <typename ViewType>
void ResizeColumnsToContent(ViewType *vt)
{
    vt->resizeColumnsToContents();
}

template <>
inline void ResizeColumnsToContent<QTreeView>(QTreeView *)
{
}

template <typename ViewType>
void InitView(ViewType *vt)
{}

template <>
inline void InitView<QTreeView>(QTreeView *tv)
{
    tv->setAlternatingRowColors(true);
    tv->setItemDelegate(new PgLabItemDelegate(tv));
    tv->setWordWrap(false);
}


template <typename TableModel, typename ViewType = PgLabTableView>
class PgLabTableViewHelper {
public:

    PgLabTableViewHelper(QWidget * parent, TableModel *tableModel)
    {
        m_itemView = new ViewType(parent);
        InitView(m_itemView);
        m_dataModel = tableModel;
        m_sortFilter = new QSortFilterProxyModel(parent);
        m_sortFilter->setSourceModel(m_dataModel);
        m_itemView->setModel(m_sortFilter);
        m_itemView->setSortingEnabled(true);
        m_sortFilter->sort(0, Qt::AscendingOrder);

    }

    PgLabTableViewHelper(QWidget * parent)
        : PgLabTableViewHelper(parent, new TableModel(parent))
    {}

    ViewType *itemView() const
    {
        return m_itemView;
    }

    TableModel *dataModel() const
    {
        return m_dataModel;
    }

    QSortFilterProxyModel *sortFilter() const
    {
        return m_sortFilter;
    }

    void setCatalog(std::shared_ptr<PgDatabaseCatalog> cat)
    {
        m_dataModel->setCatalog(cat);
        ResizeColumnsToContent(m_itemView);
    }

    QModelIndex currentSourceIndex() const
    {
        QModelIndex index = m_itemView->selectionModel()->currentIndex();
        if (!index.isValid())
            return index;

        return m_sortFilter->mapToSource(index);
    }

    typename TableModel::RowItem rowItemForSourceRow(QModelIndex index) const
    {
        return m_dataModel->rowItem(index);
    }

    typename TableModel::RowItem rowItemForProxyIndex(QModelIndex index)
    {
        QModelIndex sourceIndex = m_sortFilter->mapToSource(index);
        return m_dataModel->rowItem(sourceIndex);
    }

    typename TableModel::RowItem rowItemForProxyRow(int row) const
    {
        return rowItemForProxyIndex(m_sortFilter->index(row, 0, QModelIndex()));
    }

    std::optional<typename TableModel::RowItem> currentRowItem() const
    {
        auto index = currentSourceIndex();
        if (!index.isValid())
            return {};

        return rowItemForSourceRow(index);
    }


private:
    ViewType *m_itemView = nullptr;
    TableModel *m_dataModel = nullptr;
    QSortFilterProxyModel *m_sortFilter = nullptr;
};
