#include "SequenceModel.h"
#include "catalog/PgDatabaseCatalog.h"
#include "catalog/PgNamespace.h"
#include "catalog/PgSequenceContainer.h"

SequenceModel::SequenceModel(QObject * parent)
	: QAbstractTableModel(parent)
{}

QVariant SequenceModel::headerData(int section, Qt::Orientation orientation, int role) const
{
	if (orientation == Qt::Horizontal) {
		if (role == Qt::DisplayRole) {
			switch (section) {
			case NameCol: return tr("Name");
			case SchemaCol: return tr("Schema");
			case OwnerCol: return tr("Owner");
			case LastCol: return tr("Last");
			case StartCol: return tr("Start");
			case MinCol: return tr("Min");
			case MaxCol: return tr("Max");
			case IncrementCol: return tr("Inc");
			case CacheCol: return tr("Cached");
			case CycledCol: return tr("Cycled");
			case CalledCol: return tr("Called");
			case AclCol: return tr("ACL");
			}
		}
	}
	return {};
}

void SequenceModel::setCatalog(std::shared_ptr<const PgDatabaseCatalog> cat)
{
	if (cat != m_catalog) {
		m_catalog = cat;
		refreshConnection = connect(m_catalog.get(), &PgDatabaseCatalog::refreshed,
										this, &SequenceModel::refresh);
	}
	refresh();
}

void SequenceModel::setNamespaceFilter(NamespaceFilter filter)
{
	m_namespaceFilter = filter;
	refresh();
}

void SequenceModel::refresh()
{
	if (!m_catalog)
		return;

	beginResetModel();

	auto && seqs = m_catalog->sequences();
	m_sequences.clear();
	for (auto&& s : *seqs) {
		bool add = false;
		switch (m_namespaceFilter) {
		case NamespaceFilter::User:
			add = !s.ns().isSystemCatalog();
			break;
		case NamespaceFilter::PgCatalog:
			add = s.ns().objectName() == "pg_catalog";
			break;
		case NamespaceFilter::InformationSchema:
			add = s.ns().objectName() == "information_schema";
			break;
		}
		if (add)
			m_sequences.push_back(s);
	}

	endResetModel();
}

PgSequence SequenceModel::sequence(int row) const
{
	return m_sequences.at(static_cast<size_t>(row));
}

int SequenceModel::rowCount(const QModelIndex &) const
{
	return static_cast<int>(m_sequences.size());
}

int SequenceModel::columnCount(const QModelIndex &) const
{
	return colCount;
}

QVariant SequenceModel::data(const QModelIndex &index, int role) const
{
	if (m_sequences.empty())
		return {};

	int row = index.row();
	auto && seq = m_sequences.at(static_cast<size_t>(row));
	if (role == Qt::DisplayRole) {
		switch (index.column()) {
		case NameCol: return seq.objectName();
		case SchemaCol: return seq.nsName();
		case OwnerCol: return seq.ownerName();
		case LastCol: return seq.last;
		case StartCol: return seq.start;
		case MinCol: return seq.min;
		case MaxCol: return seq.max;
		case IncrementCol: return seq.increment;
		case CacheCol: return seq.cache;
		case CycledCol: return seq.cycled;
		case CalledCol: return seq.called;
		case AclCol: return seq.aclString();
		}
	}

	return {};
}
