ews_delete_folder_sync (CamelStore *store,
                        const gchar *folder_name,
                        GCancellable *cancellable,
                        GError **error)
{
	CamelEwsStore *ews_store = CAMEL_EWS_STORE (store);
	gchar *fid;
	gchar *trash_fid;
	gchar *trash_name;
	CamelFolderInfo *folder_info;
	CamelFolderInfo *to_update;
	gboolean success;
	gboolean is_under_trash_folder;
	GError *local_error = NULL;

	folder_info = camel_store_get_folder_info_sync (
		store, folder_name,
		CAMEL_STORE_FOLDER_INFO_RECURSIVE |
		CAMEL_STORE_FOLDER_INFO_SUBSCRIBED,
		cancellable, &local_error);

	if (folder_info == NULL) {
		g_propagate_error (error, local_error);

		return FALSE;
	}

	to_update = folder_info;

	fid = camel_ews_store_summary_get_folder_id_from_name (
		ews_store->summary, folder_name);

	if (!fid) {
		camel_folder_info_free (folder_info);

		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Folder does not exist"));
		return FALSE;
	}

	if (g_str_equal (fid, EWS_FOREIGN_FOLDER_ROOT_ID)) {
		g_free (fid);
		camel_folder_info_free (folder_info);

		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Cannot remove folder “%s”, it is used for folders of other users only"),
			folder_name);
		return FALSE;
	}

	if (g_str_equal (fid, EWS_PUBLIC_FOLDER_ROOT_ID)) {
		g_free (fid);
		camel_folder_info_free (folder_info);

		g_set_error (
			error, CAMEL_ERROR, CAMEL_ERROR_GENERIC,
			_("Cannot remove folder “%s”, it is used for public folders only"),
			folder_name);
		return FALSE;
	}

	trash_fid = camel_ews_store_summary_get_folder_id_from_folder_type (ews_store->summary, CAMEL_FOLDER_TYPE_TRASH);
	trash_name = camel_ews_store_summary_get_folder_full_name (ews_store->summary, trash_fid, &local_error);
	if (!trash_name) {
		g_free (trash_fid);
		g_free (fid);
		camel_folder_info_free (folder_info);

		g_propagate_error (error, local_error);
		return FALSE;
	}

	is_under_trash_folder = g_str_has_prefix (folder_name, trash_name);

	g_free (trash_name);

	if (!camel_ews_store_connected (ews_store, cancellable, &local_error)) {
		g_free (trash_fid);
		g_free (fid);
		camel_folder_info_free (folder_info);

		g_propagate_error (error, local_error);

		return FALSE;
	}

	if (camel_ews_store_summary_get_foreign (ews_store->summary, fid, NULL) ||
	    camel_ews_store_summary_get_public (ews_store->summary, fid, NULL)) {
		/* do not delete foreign or public folders,
		 * only remove them from local store */
		success = TRUE;
	} else {
		EEwsConnection *connection;

		connection = camel_ews_store_ref_connection (ews_store);

		success = e_ews_connection_delete_folder_sync (
			connection,
			EWS_PRIORITY_MEDIUM,
			fid, FALSE, is_under_trash_folder ? "HardDelete" : "MoveToDeletedItems",
			cancellable, &local_error);

		g_object_unref (connection);
	}

	if (!success) {
		g_free (trash_fid);
		g_free (fid);
		camel_folder_info_free (folder_info);

		camel_ews_store_maybe_disconnect (ews_store, local_error);
		g_propagate_error (error, local_error);

		return FALSE;
	}

	if (is_under_trash_folder) {
		success = camel_ews_utils_delete_folders_from_summary_recursive (ews_store, to_update, FALSE, error);

		if (!success) {
			g_free (trash_fid);
			g_free (fid);
			camel_folder_info_free (folder_info);

			g_propagate_error (error, local_error);
			return FALSE;
		}
	} else {
		camel_ews_store_summary_set_parent_folder_id (ews_store->summary, fid, trash_fid);
	}

	camel_subscribable_folder_unsubscribed (CAMEL_SUBSCRIBABLE (ews_store), folder_info);
	camel_store_folder_deleted (CAMEL_STORE (ews_store), folder_info);

	camel_folder_info_free (folder_info);

	if (!is_under_trash_folder) {
		camel_ews_store_summary_rebuild_hashes (ews_store->summary);

		folder_info = camel_ews_utils_build_folder_info (ews_store, fid);

		to_update = folder_info;
		ews_update_store_move_recursive (ews_store, to_update);
		camel_folder_info_free (folder_info);
	}

	camel_ews_store_ensure_virtual_folders (ews_store);
	camel_ews_store_summary_save (ews_store->summary, NULL);

	g_free (trash_fid);
	g_free (fid);

	return TRUE;
}