/* Copyright (c) Dovecot authors, see top-level COPYING file */

#include "imap-common.h"
#include "str.h"
#include "imap-utf7.h"
#include "imap-quote.h"
#include "imap-commands.h"
#include "mail-namespace.h"

struct namespace_order {
	int secondary_order;
	struct mail_namespace *ns;
};

static int namespace_order_cmp(const struct namespace_order *no1,
			       const struct namespace_order *no2)
{
	if (no1->ns->set->order < no2->ns->set->order)
		return -1;
	if (no1->ns->set->order > no2->ns->set->order)
		return 1;

	if (no1->secondary_order < no2->secondary_order)
		return -1;
	if (no1->secondary_order > no2->secondary_order)
		return 1;
	return 0;
}

static void
list_namespaces(struct mail_namespace *ns, enum mail_namespace_type type,
		string_t *str, bool utf8)
{
	enum imap_quote_flags qflags = (utf8 ? IMAP_QUOTE_FLAG_UTF8 : 0);
	ARRAY(struct namespace_order) ns_order;
	struct namespace_order *no;
	unsigned int count = 0;
	string_t *mutf7_prefix;

	t_array_init(&ns_order, 4);

	while (ns != NULL) {
		if (ns->type == type &&
		    (ns->flags & NAMESPACE_FLAG_HIDDEN) == 0) {
			no = array_append_space(&ns_order);
			no->ns = ns;
			no->secondary_order = ++count;
		}
		ns = ns->next;
	}

	if (array_count(&ns_order) == 0) {
		str_append(str, "NIL");
		return;
	}
	array_sort(&ns_order, namespace_order_cmp);

	mutf7_prefix = (utf8 ? NULL : t_str_new(64));
	str_append_c(str, '(');
	array_foreach_modifiable(&ns_order, no) {
		const char *prefix = no->ns->prefix;
		char ns_sep;

		ns_sep = mail_namespace_get_sep(no->ns);
		str_append_c(str, '(');

		if (!utf8) {
			str_truncate(mutf7_prefix, 0);
			if (imap_utf8_to_utf7(prefix, mutf7_prefix) < 0) {
				i_panic("LIST: Namespace prefix not UTF-8: %s",
					prefix);
			}
			prefix = str_c(mutf7_prefix);
		}

		imap_append_string(str, prefix, qflags);
		str_append(str, " \"");
		if (ns_sep == '\\')
			str_append_c(str, '\\');
		str_append_c(str, ns_sep);
		str_append(str, "\")");
	}
	str_append_c(str, ')');
}

bool cmd_namespace(struct client_command_context *cmd)
{
	struct client *client = cmd->client;
	string_t *str;

	str = t_str_new(256);
	str_append(str, "* NAMESPACE ");

	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_PRIVATE, str, cmd->utf8);
	str_append_c(str, ' ');
	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_SHARED, str, cmd->utf8);
	str_append_c(str, ' ');
	list_namespaces(client->user->namespaces,
			MAIL_NAMESPACE_TYPE_PUBLIC, str, cmd->utf8);

	client_send_line(client, str_c(str));
	client_send_tagline(cmd, "OK Namespace completed.");
	return TRUE;
}
