/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/***************************************************************************
 *            kolab-util-backend.c
 *
 *  Mon Jan 17 11:16:52 2011
 *  Copyright  2011  Christian Hilberg
 *  <hilberg@kernelconcepts.de>
 ****************************************************************************/

/*
 * This program 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 2.1 of the License, or (at your option) any later version.
 *
 * This program 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 this program; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor Boston, MA 02110-1301,  USA
 */

/*----------------------------------------------------------------------------*/

#include <config.h>

#include <string.h>
#include <time.h>

#include <glib/gi18n-lib.h>

#include <libical/ical.h>
#include <libedataserver/e-source.h>

#include <libekolabutil/camel-system-headers.h>
#include <libekolabutil/kolab-util-camel.h>

#include "kolab-mail-access.h"

#include "kolab-util-backend.h"

/*----------------------------------------------------------------------------*/

static const gchar *kolab_sync_strategy_desc[KOLAB_SYNC_LAST_STRATEGY] = {
	N_(KOLAB_STRATEGY_DESC_NEWEST),
	N_(KOLAB_STRATEGY_DESC_SERVER),
	N_(KOLAB_STRATEGY_DESC_CLIENT),
	N_(KOLAB_STRATEGY_DESC_DUPE)
};

static const gchar *kolab_tls_variant_desc[KOLAB_TLS_LAST_VARIANT] = {
	N_(KOLAB_TLS_DESC_VARIANT_NONE),
	N_(KOLAB_TLS_DESC_VARIANT_SSL),
	N_(KOLAB_TLS_DESC_VARIANT_TLS)
};

/*----------------------------------------------------------------------------*/
/* local statics */

/*----------------------------------------------------------------------------*/
/* GError for libekolabbackend */

GQuark
kolab_util_backend_error_quark (void)
{
	static GQuark quark = 0;

	if (G_UNLIKELY (quark == 0)) {
		const gchar *string = "kolab-backend-error-quark";
		quark = g_quark_from_static_string (string);
	}

	return quark;
}

/*----------------------------------------------------------------------------*/
/* calendar name <-> folder name translation */

gchar*
kolab_util_backend_sourcename_new_from_foldername (const gchar *foldername,
                                                   GError **err)
{
	/* foldername can be NULL */
	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);

	/* FIXME do input sanitization here, provide real implementation */

	/* TODO
	 * - do we need a full mapping of calendar names to folder names?
	 * - can we use Camel infrastructure for checking of mailbox names?
	 */

	if (foldername == NULL)
		return NULL;

	return g_strdup (foldername);
}

gchar*
kolab_util_backend_foldername_new_from_sourcename (const gchar *sourcename,
                                                   GError **err)
{
	/* sourcename may be NULL */
	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);

	if (sourcename == NULL)
		return NULL;

	return g_strdup (sourcename);
}

/**
 * kolab_util_backend_get_relative_path_from_uri:
 * @uri: An URI string
 *
 * Extracts the path from the given uri. Leading "/" are removed.
 *
 * Returns: A newly allocated string containing the uri, or NULL.
 */
gchar *
kolab_util_backend_get_relative_path_from_uri (const gchar *uri)
{
	CamelURL *c_url = NULL;
	gchar *tmp = NULL;
	gchar *path = NULL;
	GError *tmp_err = NULL;

	c_url = camel_url_new (uri, &tmp_err);
	if (c_url == NULL) {
		g_warning ("%s()[%u] error: %s", __func__, __LINE__, tmp_err->message);
		g_error_free (tmp_err);
		return NULL;
	}
	tmp = g_strdup (c_url->path);
	camel_url_free (c_url);
	if (tmp[0] == '/') {
		path = g_strdup (tmp+1);
		g_free (tmp);
	}
	else {
		path = tmp;
	}

	return path;
} /* kolab_util_backend_get_relative_path_from_uri () */

gchar*
kolab_util_backend_get_protocol_from_uri (const gchar *uri)
{
	CamelURL *c_url = NULL;
	gchar *proto = NULL;
	GError *tmp_err = NULL;

	c_url = camel_url_new (uri, &tmp_err);
	if (c_url == NULL) {
		g_warning ("%s()[%u] error: %s", __func__, __LINE__, tmp_err->message);
		g_error_free (tmp_err);
		return NULL;
	}
	proto = g_strdup (c_url->protocol);
	camel_url_free (c_url);

	return proto;
}

static gint
kolab_util_misc_generic_integer_from_property (const gchar *prop_str,
                                               gint DEFAULT_VALUE)
{
	guint64 tmp_value;
	gint prop_value;
	gchar *endptr = NULL;

	if (prop_str == NULL) /* Empty property -> use DEFAULT_VALUE. */
		return DEFAULT_VALUE;

	tmp_value = g_ascii_strtoull (prop_str, &endptr, 10);
	if ((tmp_value == 0) && (endptr == prop_str)) {
		/* This is a conversion error. Use DEFAULT_VALUE instead. */
		prop_value = DEFAULT_VALUE;
	} else if (tmp_value > G_MAXINT) {
		/* Overflow, handle gracefully: defaulting to DEFAULT_VALUE.
		 * Any other error leads to sync_value being zero which we
		 * assume to be the default value anyway */
		prop_value = DEFAULT_VALUE;
	} else
		prop_value = (gint) tmp_value;
	return prop_value;
} /* kolab_util_misc_generic_integer_from_property () */

KolabSyncStrategyID
kolab_util_misc_sync_value_from_property (const gchar *sync_prop)
{
	KolabSyncStrategyID sid = KOLAB_SYNC_STRATEGY_DEFAULT;

	if (sync_prop == NULL)
		return KOLAB_SYNC_STRATEGY_DEFAULT;

	sid = kolab_util_misc_generic_integer_from_property (sync_prop,
	                                                     KOLAB_SYNC_STRATEGY_DEFAULT);
	return sid;
} /* kolab_util_misc_sync_value_from_property () */

KolabTLSVariantID
kolab_util_misc_tls_variant_from_property (const gchar *tls_variant)
{
	KolabTLSVariantID tvid = KOLAB_TLS_VARIANT_DEFAULT;

	if (tls_variant == NULL)
		return KOLAB_TLS_VARIANT_DEFAULT;

	tvid = kolab_util_misc_generic_integer_from_property (tls_variant,
	                                                      KOLAB_TLS_VARIANT_DEFAULT);
	return tvid;
} /* kolab_util_misc_tls_variant_from_property () */

KolabReqPkcs11
kolab_util_misc_req_pkcs11_from_property (const gchar *req_pkcs11_prop)
{
	KolabReqPkcs11 pkreq = KOLAB_PKCS11_INFRASTRUCTURE_DEFAULT;

	if (req_pkcs11_prop == NULL)
		return KOLAB_PKCS11_INFRASTRUCTURE_DEFAULT;

	pkreq = kolab_util_misc_generic_integer_from_property (req_pkcs11_prop,
	                                                       KOLAB_PKCS11_INFRASTRUCTURE_DEFAULT);
	return pkreq;
}

void
kolab_util_backend_koma_table_cleanup_cb (gpointer data,
                                          GObject *object,
                                          gboolean is_last_ref)
{
	KolabMailAccess *koma = KOLAB_MAIL_ACCESS (object);
	GHashTable *koma_table = (GHashTable *) data;
	const gchar *servername = NULL;
	const gchar *username = NULL;
	gchar *user_at_server = NULL;
	KolabSettingsHandler *ksettings = NULL;
	/* gboolean ok; */
	g_debug ("%s()[%u] called.", __func__, __LINE__);

	g_assert (data != NULL);
	g_assert (G_IS_OBJECT (object));
	(void)is_last_ref;

	ksettings = kolab_mail_access_get_settings_handler (koma);
	servername = kolab_settings_handler_get_char_field (ksettings,
	                                                    KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_SERVER_NAME,
	                                                    NULL);
	username = kolab_settings_handler_get_char_field (ksettings,
	                                                  KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
	                                                  NULL);
	user_at_server = g_strdup_printf ("%s@%s", username, servername);
	(void)g_hash_table_remove (koma_table, user_at_server);

	g_free (user_at_server);
	g_object_remove_toggle_ref (object,
	                            kolab_util_backend_koma_table_cleanup_cb,
	                            data);
} /* kolab_util_backend_koma_table_cleanup_cb () */

void
kolab_util_backend_modtime_set_on_econtact (EContact *econtact)
{
	time_t rawtime;
	struct tm *ts = NULL;
	gchar *buf = NULL;

	g_assert (E_IS_CONTACT (econtact));

	time (&rawtime);
	ts = gmtime (&rawtime);
	buf = g_new0 (gchar, 21);
	strftime (buf, 21, "%Y-%m-%dT%H:%M:%SZ", ts); /* same as in contact-i-to-e.c */
	e_contact_set (econtact, E_CONTACT_REV, buf);
	g_free (buf);
} /* kolab_util_backend_modtime_set_on_econtact () */

void
kolab_util_backend_modtime_set_on_ecalcomp (ECalComponent *ecalcomp)
{
	struct icaltimetype itt;

	g_assert (E_IS_CAL_COMPONENT (ecalcomp));

	itt = icaltime_current_time_with_zone (NULL); /* need UTC here, hence NULL timezone */
	e_cal_component_set_last_modified (ecalcomp, &itt);
} /* kolab_util_backend_modtime_set_on_ecalcomp () */

void
kolab_util_backend_prepare_settings (KolabSettingsHandler *ksettings,
                                     ESource *esource,
                                     const gchar *servername,
                                     const gchar *username,
                                     const gchar *password,
                                     const gchar *sourcename,
                                     const KolabSyncStrategyID *sync_value)
{
	/* Note: Currently (2.30), there is no good way of returning errors from
	 * the backend to the frontends. So this helper function simply notifies
	 * on stdout/stderr and proceeds.
	 */
	const gchar *prop_str = NULL;
	KolabTLSVariantID enc_value;
	KolabReqPkcs11 req_pkcs11_value;

	GError *error = NULL;
	g_debug ("%s()[%u] called.", __func__, __LINE__);
	if (esource != NULL) {
		prop_str = e_source_peek_uid (esource);
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_ESOURCE_UID,
		                                             g_strdup (prop_str),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
		prop_str = e_source_get_uri (esource);
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_URI,
		                                             g_strdup (prop_str),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
		prop_str = e_source_get_property (esource, KOLAB_TLS_VARIANT_PROP);
		enc_value = kolab_util_misc_tls_variant_from_property (prop_str);
		(void)kolab_settings_handler_set_uint_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_UINT_FIELD_TLS_VARIANT,
		                                             enc_value,
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
		prop_str = e_source_get_property (esource, KOLAB_REQ_PKCS11_PROP);
		req_pkcs11_value = kolab_util_misc_req_pkcs11_from_property (prop_str);
		if (req_pkcs11_value == KOLAB_PKCS11_INFRASTRUCTURE_ENABLE) {
			prop_str = e_source_get_property (esource, KOLAB_PKCS11_PIN_PROP);
		}
		else {
			prop_str = NULL;
		}
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_PKCS11_USER_PIN,
		                                             g_strdup (prop_str),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
	}
	if (servername != NULL) {
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_SERVER_NAME,
		                                             g_strdup (servername),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
	}
	if (username != NULL) {
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
		                                             g_strdup (username),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
	}
	if (password != NULL) {
		(void)kolab_settings_handler_set_char_field (ksettings,
		                                             KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_PASSWORD,
		                                             g_strdup (password),
		                                             &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
	}
	if (sync_value != NULL) {
		(void)kolab_settings_handler_set_value (ksettings,
		                                        KOLAB_SETTINGS_HANDLER_TBL_SYNCSTRATEGY,
		                                        sourcename,
		                                        GUINT_TO_POINTER (*sync_value),
		                                        &error);
		if (error != NULL) {
			g_warning ("%s()[%u] error: %s", __func__, __LINE__, error->message);
			g_error_free (error);
			error = NULL;
		}
	}
} /* kolab_util_backend_prepare_settings () */

gboolean
kolab_util_backend_sqlite_db_new_open (KolabUtilSqliteDb **kdb,
                                       KolabSettingsHandler *ksettings,
                                       const gchar *dbfilename,
                                       GError **err)
{
	const gchar *dbpath = NULL;
	gboolean ok = FALSE;
	GError *tmp_err = NULL;

	g_assert ((kdb != NULL) && (*kdb == NULL));
	g_assert (KOLAB_IS_SETTINGS_HANDLER (ksettings));
	g_assert (dbfilename != NULL);
	g_return_val_if_fail (err == NULL || *err == NULL, FALSE);

	dbpath = kolab_settings_handler_get_char_field (ksettings,
	                                                KOLAB_SETTINGS_HANDLER_CHAR_FIELD_CAMEL_ACCOUNT_DIR,
	                                                &tmp_err);
	if (tmp_err != NULL) {
		g_propagate_error (err, tmp_err);
		return FALSE;
	}
	if (dbpath == NULL) {
		g_set_error (err,
		             KOLAB_BACKEND_ERROR,
		             KOLAB_BACKEND_ERROR_CAMEL,
		             _("Could not get Camel storage path for internal database"));
		return FALSE;
	}
	*kdb = kolab_util_sqlite_db_new ();
	ok = kolab_util_sqlite_db_open (*kdb,
	                                dbpath,
	                                dbfilename,
	                                &tmp_err);
	if (! ok) {
		g_propagate_error (err, tmp_err);
		return FALSE;
	}

	return TRUE;
}

/*----------------------------------------------------------------------------*/
/* mapping of description IDs to description strings */

const gchar*
kolab_util_backend_get_sync_strategy_desc (KolabSyncStrategyID id)
{
	g_assert (id < KOLAB_SYNC_LAST_STRATEGY);

	return gettext (kolab_sync_strategy_desc[id]);
}

const gchar*
kolab_util_backend_get_tls_variant_desc (KolabTLSVariantID id)
{
	g_assert (id < KOLAB_TLS_LAST_VARIANT);

	return gettext (kolab_tls_variant_desc[id]);
}

CamelURL*
kolab_util_backend_camel_url_new_from_settings (KolabSettingsHandler *ksettings,
                                                GError **err)
{
	KolabTLSVariantID tlsvariant = KOLAB_TLS_VARIANT_NONE;
	CamelURL *camel_url = NULL;
	const gchar *variant_str = NULL;
	const gchar *tmp_str = NULL;
	GError *tmp_err = NULL;

	g_assert (KOLAB_IS_SETTINGS_HANDLER (ksettings));
	g_return_val_if_fail (err == NULL || *err == NULL, NULL);

	/* create url string for session getter */
	camel_url = camel_url_new (KOLAB_CAMELURL_DUMMY_URL, NULL);
	camel_url_set_protocol (camel_url, KOLAB_CAMEL_PROVIDER_PROTOCOL);
	tmp_str = kolab_settings_handler_get_char_field (ksettings,
	                                                 KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_SERVER_NAME,
	                                                 &tmp_err);
	if (tmp_err != NULL) {
		camel_url_free (camel_url);
		g_propagate_error (err, tmp_err);
		return NULL;
	}
	if (tmp_str == NULL) {
		camel_url_free (camel_url);
		/* FIXME mark as a translatable string */
		g_set_error (err,
		             KOLAB_BACKEND_ERROR,
		             KOLAB_BACKEND_ERROR_INTERNAL,
		             "Internal inconsistency detected: Kolab server name not set");
		return NULL;

	}
	camel_url_set_host (camel_url, tmp_str);
	tmp_str = kolab_settings_handler_get_char_field (ksettings,
	                                                 KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
	                                                 &tmp_err);
	if (tmp_err != NULL) {
		camel_url_free (camel_url);
		g_propagate_error (err, tmp_err);
		return NULL;
	}
	if (tmp_str == NULL) {
		camel_url_free (camel_url);
		/* FIXME mark as a translatable string */
		g_set_error (err,
		             KOLAB_BACKEND_ERROR,
		             KOLAB_BACKEND_ERROR_INTERNAL,
		             "Internal inconsistency detected: Kolab User ID not set");
		return NULL;

	}
	camel_url_set_user (camel_url, tmp_str);
	tlsvariant = kolab_settings_handler_get_uint_field (ksettings,
	                                                    KOLAB_SETTINGS_HANDLER_UINT_FIELD_TLS_VARIANT,
	                                                    &tmp_err);
	if (tmp_err != NULL) {
		camel_url_free (camel_url);
		g_propagate_error (err, tmp_err);
		return NULL;
	}

	switch (tlsvariant) {
	case KOLAB_TLS_VARIANT_SSL:
		variant_str = KOLAB_CAMELURL_TLSVARIANT_SSL;
		break;
	case KOLAB_TLS_VARIANT_STARTTLS:
		variant_str = KOLAB_CAMELURL_TLSVARIANT_STARTTLS;
		break;
	default:
		variant_str = KOLAB_CAMELURL_TLSVARIANT_NONE;
	}

	camel_url_set_param (camel_url,
	                     KOLAB_CAMELURL_PARAM_SSL,
	                     variant_str);
	return camel_url;
}

gchar*
kolab_util_backend_account_uid_new_from_settings (KolabSettingsHandler *ksettings,
                                                  GError **err)
{
	const gchar *user = NULL;
	const gchar *server = NULL;
	const gchar *esource_uid = NULL;
	gchar *account_uid = NULL;
	gchar *tmp_str = NULL;
	GError *tmp_err = NULL;

	g_assert (KOLAB_IS_SETTINGS_HANDLER (ksettings));
	g_return_val_if_fail (err == NULL || *err == NULL, NULL);

	esource_uid = kolab_settings_handler_get_char_field (ksettings,
	                                                     KOLAB_SETTINGS_HANDLER_CHAR_FIELD_ESOURCE_UID,
	                                                     &tmp_err);
	if (tmp_err != NULL) {
		g_warning ("%s: %s", __func__, tmp_err->message);
		g_error_free (tmp_err);
		tmp_err = NULL;
	}

	if (esource_uid != NULL) {
		tmp_str = g_strdup (esource_uid);
		goto done;
	}

	/* fallback in case we don't have an ESource UID set */

	user = kolab_settings_handler_get_char_field (ksettings,
	                                              KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_USER_NAME,
	                                              &tmp_err);
	if (tmp_err != NULL) {
		g_propagate_error (err, tmp_err);
		return NULL;
	}
	server = kolab_settings_handler_get_char_field (ksettings,
	                                                KOLAB_SETTINGS_HANDLER_CHAR_FIELD_KOLAB_SERVER_NAME,
	                                                &tmp_err);
	if (tmp_err != NULL) {
		g_propagate_error (err, tmp_err);
		return NULL;
	}

	tmp_str = g_strconcat (user, "@", server, NULL);

 done:

	account_uid = g_strconcat (KOLAB_CAMEL_PROVIDER_PROTOCOL, "__", tmp_str, NULL);
	g_free (tmp_str);

	return account_uid;
}

KolabMailAccessOpmodeID
kolab_util_backend_deploy_mode_by_koma (KolabMailAccess *koma,
                                        KolabMailAccessOpmodeID koma_mode,
                                        GCancellable *cancellable,
                                        GError **error)
{
	KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	GError *tmp_err = NULL;
	gboolean ok = FALSE;

	g_debug ("%s()[%u] called.", __func__, __LINE__);

	if (koma != NULL) g_assert (KOLAB_IS_MAIL_ACCESS (koma));
	g_assert (koma_mode < KOLAB_MAIL_ACCESS_LAST_OPMODE);
	/* cancellable may be NULL */
	g_return_val_if_fail (error == NULL || *error == NULL, KOLAB_MAIL_ACCESS_OPMODE_INVAL);

	if (koma == NULL) {
		g_debug ("%s()[%u] error: KolabMailAccess object not existent.",
		         __func__, __LINE__);
		/* FIXME set GError */
		return KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	}

	/* get current KolabMailAccess operational mode */
	tmp_mode = kolab_mail_access_get_opmode (koma, &tmp_err);
	if (tmp_err != NULL) {
		g_propagate_error (error, tmp_err);
		return KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	}
	if (tmp_mode < KOLAB_MAIL_ACCESS_OPMODE_OFFLINE) {
		g_debug ("%s()[%u] KolabMailAccess object not ready, deferring.",
		         __func__, __LINE__);
		return tmp_mode;
	}

	/* set new KolabMailAccess operational mode */
	ok = kolab_mail_access_set_opmode (koma,
	                                   koma_mode,
	                                   cancellable,
	                                   &tmp_err);
	if (! ok) {
		g_propagate_error (error, tmp_err);
		return KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	}

	return koma_mode;
}

gboolean
kolab_util_backend_deploy_mode_by_backend (KolabMailAccess *koma,
                                           gboolean online,
                                           GCancellable *cancellable,
                                           GError **error)
{
	KolabMailAccessOpmodeID koma_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	KolabMailAccessOpmodeID tmp_mode = KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	GError *tmp_err = NULL;

	g_debug ("%s()[%u] called.", __func__, __LINE__);

	if (koma != NULL) g_assert (KOLAB_IS_MAIL_ACCESS (koma));
	g_assert (koma_mode < KOLAB_MAIL_ACCESS_LAST_OPMODE);
	/* cancellable may be NULL */
	g_return_val_if_fail (error == NULL || *error == NULL, KOLAB_MAIL_ACCESS_OPMODE_INVAL);

	if (koma == NULL) {
		g_debug ("%s()[%u] error: KolabMailAccess object not existent.",
		         __func__, __LINE__);
		/* FIXME set GError */
		return KOLAB_MAIL_ACCESS_OPMODE_INVAL;
	}

	switch (online) {
	case FALSE:
		koma_mode = KOLAB_MAIL_ACCESS_OPMODE_OFFLINE;
		break;
	default:
		koma_mode = KOLAB_MAIL_ACCESS_OPMODE_ONLINE;
	}
	tmp_mode = kolab_util_backend_deploy_mode_by_koma (koma,
	                                                   koma_mode,
	                                                   cancellable,
	                                                   &tmp_err);
	if (tmp_err != NULL)
		g_propagate_error (error, tmp_err);

	return tmp_mode == koma_mode;
}
