#include "PgServerObject.h"
#include "PgAuthIdContainer.h"
#include "PgDatabaseCatalog.h"
#include "SqlFormattingUtils.h"
#include <QStringBuilder>


void PgServerObject::setOwnerOid(Oid oid)
{
	m_ownerOid = oid;
	m_owner = catalog().authIds()->getByKey(oid);
}

Oid PgServerObject::ownerOid() const
{
	return m_ownerOid;
}

bool PgServerObject::hasOwner() const
{
	return m_ownerOid != InvalidOid;
}

QString PgServerObject::ownerName() const
{
	return m_owner->objectName();
}

const PgAuthId* PgServerObject::owner() const
{
	return m_owner;
}


QString PgServerObject::alterOwnerSql(const QString& ident) const
{
	return QString("\nALTER %1 OWNER TO %2;").arg(ident, quoteIdent(ownerName()));
}


void PgServerObject::setAcls(boost::optional<AclList> acls)
{
	m_acls = std::move(acls);
}

QString PgServerObject::aclString() const
{
	QString result;
	if (m_acls) {
		for (auto&& acl : *m_acls) {
			if (result.isEmpty()) result += "{";
			else result += ",";
			result += acl.singleString();
		}
		if (!result.isEmpty())
			result += "}";
	}
	return result;
}

QString PgServerObject::grantSql() const
{
	//	object_type_and_name => TABLE X
	//	GRANT ??? ON object_type_and_name TO ...

	const QString column; ///< \todo should be set when called on a column object

	QString all_pattern = aclAllPattern();
	if (all_pattern.isEmpty())
		return {};

	QString grant;
	auto  grant_on_object = QString("%1 %2").arg(typeName(), fullyQualifiedQuotedObjectName());
	if (m_acls) {
		for (auto&& acl : *m_acls) {
			grant += acl.sql(all_pattern, grant_on_object, column);
		}
	}
	else {
		// PUBLIC, no priviliges
		grant += PgAcl("=").sql(all_pattern, grant_on_object, column);
		// owner no privileges
		if (hasOwner())
			grant += PgAcl(ownerName() + "=").sql(all_pattern, grant_on_object, column);
	}
	return grant;
}

QString PgServerObject::aclAllPattern() const
{
	return {};
}

QString PgServerObject::dropSql() const
{
    return "DROP " % ddlTypeName() % " " % fullyQualifiedQuotedObjectName() % ";";
}

QString PgServerObject::createSql() const
{
    return {};
}

QString PgServerObject::commentSql() const
{
    if (description.isEmpty())
        return {};

    return "COMMENT ON " + typeName() + " " + fullyQualifiedQuotedObjectName()
                + " IS " + escapeLiteral(description) + ";";
}

QString PgServerObject::ddlTypeName() const
{
    return typeName();
}

