#ifndef PGATTRIBUTE_H
#define PGATTRIBUTE_H

#include "Pgsql_declare.h"
#include <QString>
#include <libpq-fe.h>
#include <tuple>

class PgClass;
class PgDatabaseCatalog;

class PgAttribute {
public:
    enum class Identity {
        None,
        Always,
        ByDefault
    };
    enum class Generated {
        None,
        Stored
    };

    class Key {
    public:
        Key() = default;
        Key(Oid relationId, int16_t num)
            : RelationId(relationId)
            , Num(num)
        {}

        std::strong_ordering operator <=> (const Key &rhs) const = default;
    private:
        Oid RelationId = InvalidOid;
        int16_t Num = 0;
    };

	Oid relid = InvalidOid;
	QString name;
	Oid typid = InvalidOid;
	int32_t stattarget = 0;
	int16_t num = 0;
	int32_t ndims = 0; // array dimensions
	int32_t typmod = -1;
	bool notnull = false;
	bool hasdef = false;
	char identity = '\0';
    char generated = '\0';
	bool isdropped = false;
	bool islocal = true;
	Oid collation = InvalidOid;
	QString acl;
	QString options;

    Identity getIdentity() const;
    Generated getGenerated() const;

	QString defaultValue; ///< Comes from pg_attrdef table
	QString sername, serschema; // serial sequence name and schema
    QString description; ///< from pg_description

    Key key() const
    {
        return Key(relid, num);
    }

    std::strong_ordering operator <=> (const Key& rhs) const
    {
        return key() <=> rhs;
    }

    bool operator==(const Key &k) const
    {
        return key() == k;
    }

	bool operator==(const QString &n) const { return name == n; }
	bool operator<(const PgAttribute &rhs) const { return relid < rhs.relid || (relid == rhs.relid && num < rhs.num); }

	/// Return the part of the SQL create statement that can be reused for both the CREATE TABLE and ALTER TABLE ADD COLUMN
	QString columnDefinition(const PgDatabaseCatalog &cat) const;
	QString alterTableAddColumn(const PgDatabaseCatalog &cat, const PgClass &table) const;
	QString alterTableDropColumn(const PgDatabaseCatalog &cat, const PgClass &table) const;
    QString commentStatement(const PgDatabaseCatalog &cat, const PgClass &table) const;

	bool isSerial() const { return !sername.isEmpty(); }
};

#endif // PGATTRIBUTE_H
