/*
	Copyright (c) 2010 by Dennis Schridde

	This file is part of dovecot-metadata.

	dovecot-metadata is free software: you can redistribute it and/or modify
	it under the terms of the GNU Lesser General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	dovecot-metadata is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU Lesser General Public License for more details.

	You should have received a copy of the GNU Lesser General Public License
	along with dovecot-metadata.  If not, see <http://www.gnu.org/licenses/>.
*/
#include "metadata-mail-storage-module.h"

#include "dict.h"
#include "module-context.h"
#include "mail-storage-private.h"

#include "mailbox-ext.h"
#include "metadata-mail-user-module-private.h"

#define METADATA_MAILBOX_CONTEXT(obj) MODULE_CONTEXT(obj, metadata_mailbox_module)

static MODULE_CONTEXT_DEFINE_INIT(metadata_mailbox_module, &mail_storage_module_register);

static int
metadata_mailbox_delete(struct mailbox *box) {
	union mailbox_module_context *mbox = METADATA_MAILBOX_CONTEXT(box);
	if (mbox == NULL) {
		i_error("metadata: found NULL mailbox, can't delete it");
		return -1;
	}

	struct mail_storage *storage = mailbox_get_storage(box);
	struct mail_user *user = mail_storage_get_user(storage);
	struct metadata_mail_user *muser = METADATA_USER_CONTEXT(user);
	if (muser == NULL) {
		i_error("metadata: found NULL user, can't delete mailbox");
		return -1;
	}

	struct dict_transaction_context *dt = dict_transaction_begin(muser->dict);

	const char *name;
	const char *value;

	const char *skey = t_strconcat(DICT_PATH_SHARED, mailbox_get_guid_string(box), NULL);

	struct dict_iterate_context *siter = dict_iterate_init(muser->dict, skey, DICT_ITERATE_FLAG_RECURSE);
	while (dict_iterate(siter, &name, &value)) {
		dict_unset(dt, name);
	}
	if (dict_iterate_deinit(&siter) < 0) {
		i_error("metadata: dict iteration (" DICT_PATH_SHARED ") failed, can't update dict");
		return -1;
	}

	const char *pkey = t_strconcat(DICT_PATH_PRIVATE, mailbox_get_guid_string(box), NULL);

	struct dict_iterate_context *piter = dict_iterate_init(muser->dict, pkey, DICT_ITERATE_FLAG_RECURSE);
	while (dict_iterate(piter, &name, &value)) {
		dict_unset(dt, name);
	}
	if (dict_iterate_deinit(&piter) < 0) {
		i_error("metadata: dict iteration (" DICT_PATH_PRIVATE ") failed, can't update dict");
		return -1;
	}

#if DOVECOT_PREREQ(2,2)
	int super_ret = mbox->super.delete_box(box);
#else
	int super_ret = mbox->super.delete(box);
#endif
	if (super_ret < 0) {
		dict_transaction_rollback(&dt);
	} else if (dict_transaction_commit(&dt) < 0) {
		i_error("metadata: dict commit failed");
		return -1;
	}

	return super_ret;
}

void metadata_mailbox_allocated(struct mailbox *box) {
	union mailbox_module_context *mbox = p_new(box->pool, union mailbox_module_context, 1);
	mbox->super = box->v;
#if DOVECOT_PREREQ(2,2)
	box->v.delete_box = metadata_mailbox_delete;
#else
	box->v.delete = metadata_mailbox_delete;
#endif

	MODULE_CONTEXT_SET_SELF(box, metadata_mailbox_module, mbox);
}
