/*-------------------------------------------------------------------------
 *
 * deparse_collation_stmts.c
 *	  All routines to deparse collation statements.
 *	  This file contains all entry points specific for type statement deparsing as well as
 *	  functions that are currently only used for deparsing of the type statements.
 *
 * Copyright (c) Citus Data, Inc.
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "catalog/namespace.h"
#include "lib/stringinfo.h"
#include "nodes/value.h"
#include "utils/builtins.h"

#include "distributed/deparser.h"
#include "distributed/citus_ruleutils.h"

static void AppendDropCollationStmt(StringInfo buf, DropStmt *stmt);
static void AppendRenameCollationStmt(StringInfo buf, RenameStmt *stmt);
static void AppendAlterCollationSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt);
static void AppendAlterCollationOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt);
static void AppendNameList(StringInfo buf, List *objects);


/*
 * DeparseDropCollationStmt builds and returns a string representing the DropStmt
 */
char *
DeparseDropCollationStmt(Node *node)
{
	DropStmt *stmt = castNode(DropStmt, node);
	StringInfoData str = { 0 };
	initStringInfo(&str);

	Assert(stmt->removeType == OBJECT_COLLATION);

	AppendDropCollationStmt(&str, stmt);

	return str.data;
}


/*
 * AppendDropCollationStmt appends a string representing the DropStmt to a buffer
 */
static void
AppendDropCollationStmt(StringInfo buf, DropStmt *stmt)
{
	appendStringInfoString(buf, "DROP COLLATION ");
	if (stmt->missing_ok)
	{
		appendStringInfoString(buf, "IF EXISTS ");
	}
	AppendNameList(buf, stmt->objects);
	if (stmt->behavior == DROP_CASCADE)
	{
		appendStringInfoString(buf, " CASCADE");
	}
}


/*
 * DeparseRenameCollationStmt builds and returns a string representing the RenameStmt
 */
char *
DeparseRenameCollationStmt(Node *node)
{
	RenameStmt *stmt = castNode(RenameStmt, node);
	StringInfoData str = { 0 };
	initStringInfo(&str);

	Assert(stmt->renameType == OBJECT_COLLATION);

	AppendRenameCollationStmt(&str, stmt);

	return str.data;
}


/*
 * AppendRenameCollationStmt appends a string representing the RenameStmt to a buffer
 */
static void
AppendRenameCollationStmt(StringInfo buf, RenameStmt *stmt)
{
	List *names = (List *) stmt->object;

	appendStringInfo(buf, "ALTER COLLATION %s RENAME TO %s;",
					 NameListToQuotedString(names),
					 quote_identifier(stmt->newname));
}


/*
 * DeparseAlterCollationSchemaStmt builds and returns a string representing the AlterObjectSchemaStmt
 */
char *
DeparseAlterCollationSchemaStmt(Node *node)
{
	AlterObjectSchemaStmt *stmt = castNode(AlterObjectSchemaStmt, node);
	StringInfoData str = { 0 };
	initStringInfo(&str);

	Assert(stmt->objectType == OBJECT_COLLATION);

	AppendAlterCollationSchemaStmt(&str, stmt);

	return str.data;
}


/*
 * AppendAlterCollationSchemaStmt appends a string representing the AlterObjectSchemaStmt to a buffer
 */
static void
AppendAlterCollationSchemaStmt(StringInfo buf, AlterObjectSchemaStmt *stmt)
{
	Assert(stmt->objectType == OBJECT_COLLATION);

	List *names = (List *) stmt->object;
	appendStringInfo(buf, "ALTER COLLATION %s SET SCHEMA %s;", NameListToQuotedString(
						 names),
					 quote_identifier(stmt->newschema));
}


/*
 * DeparseAlterCollationOwnerStmt builds and returns a string representing the AlterOwnerStmt
 */
char *
DeparseAlterCollationOwnerStmt(Node *node)
{
	AlterOwnerStmt *stmt = castNode(AlterOwnerStmt, node);
	StringInfoData str = { 0 };
	initStringInfo(&str);

	Assert(stmt->objectType == OBJECT_COLLATION);

	AppendAlterCollationOwnerStmt(&str, stmt);

	return str.data;
}


/*
 * AppendAlterCollationOwnerStmt appends a string representing the AlterOwnerStmt to a buffer
 */
static void
AppendAlterCollationOwnerStmt(StringInfo buf, AlterOwnerStmt *stmt)
{
	Assert(stmt->objectType == OBJECT_COLLATION);

	List *names = (List *) stmt->object;
	appendStringInfo(buf, "ALTER COLLATION %s OWNER TO %s;", NameListToQuotedString(
						 names),
					 RoleSpecString(stmt->newowner, true));
}


static void
AppendNameList(StringInfo buf, List *objects)
{
	ListCell *objectCell = NULL;

	foreach(objectCell, objects)
	{
		List *name = castNode(List, lfirst(objectCell));

		if (objectCell != list_head(objects))
		{
			appendStringInfo(buf, ", ");
		}

		appendStringInfoString(buf, NameListToQuotedString(name));
	}
}
