#ifndef PGCLASS_H
#define PGCLASS_H

#include "Pgsql_Value.h"
#include "PgNamespaceObject.h"
#include <QString>
#include <libpq-fe.h>
#include <boost/container/small_vector.hpp>

class PgAttribute;

enum class RelPersistence {
	Permanent, // p
	Unlogged, // u
	Temporary  // t
};

void operator<<(RelPersistence &s, const Pgsql::Value &v);

enum class RelKind
{
	Table, // r
	Index, // i
	Sequence, // S
	View,  // v
	MaterializedView, // m
	Composite, // c
	Toast, // t
    ForeignTable, // f
    PartitionedTable, // p
    PartitionedIndex // I
};

void operator<<(RelKind &s, const Pgsql::Value &v);

enum class PartitioningStrategy
{
    Hash, // h
    List, // l
    Range // r
};

void operator<<(PartitioningStrategy &s, const Pgsql::Value &v);

QString PartitionStrategyKeyword(PartitioningStrategy ps);

class PartitioningKeyItem
{
public:
    int16_t attNum;
    Oid opClass;
    Oid collation;
    // expre nodetree
    QString expression; // pg_get_expr(pg_node_tree, relation_oid)
};
using PartitioningKeyItems = boost::container::small_vector<PartitioningKeyItem, 3>;

class PgPartitionedTable
{
public:
    PartitioningStrategy strategy;
    Oid defaultPartition;

    PartitioningKeyItems keyColumns;
};


class PgClass: public PgNamespaceObject {
public:
	Oid type = InvalidOid;
	Oid oftype = InvalidOid;
	Oid am = InvalidOid;
	Oid filenode = InvalidOid;
	Oid tablespace = InvalidOid;
	int32_t pages_est = 0;
	float tuples_est = 0.0f;
	Oid toastrelid = InvalidOid;
	bool isshared = false;
	RelPersistence persistence;
	RelKind kind;
	bool hasoids = false;
	bool ispopulated;
	int frozenxid;
	int minmxid;
	std::vector<QString> options;
	QString viewdef;
    QString partitionBoundaries;
    PgPartitionedTable partitionedTable; // ignore if RelKind != PartitionedTable

	using PgNamespaceObject::PgNamespaceObject;

	QString kindString() const;
	QString createSql() const override;
	QString typeName() const override;
	QString aclAllPattern() const override;


protected:
    virtual QString ddlTypeName() const override;

private:
	mutable QString createSqlCache;

	QString createTableSql() const;
    QString generateBodySql(bool isPartition) const;
    QString generateInheritsSql() const;
    QString partitionBySql() const;
    QString partitionKeySql() const;
    QString partitionKeyItemSql(
        const PartitioningKeyItem &keyItem
    ) const;
    QString getPartitionOfName() const;
    QString generateTablespaceSql() const;
	QString createViewSql() const;
};

#endif // PGCLASS_H
