/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/***************************************************************************
 *            kolab-util-contact.c
 *
 *  2011
 *  Copyright  2011  Silvan Marco Fin
 *  <silvan@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 <libekolab/kolab-mail-access.h>

#include <libebook/e-contact.h>
#include <libecal/e-cal.h>

#include "kolab-util-contact.h"

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

/* taken from mapi, for now we just need the EContact field IDs
 * to report the fields supported by evolution-kolab
 * (is there not an EContact convenience function for that ?!?)
 */

static const struct field_element_mapping {
	EContactField field_id;
#if 0
	uint32_t mapi_id;
	gint element_type;
#endif
} mappings [] = {
	{ E_CONTACT_UID,		/* PidTagMid,			ELEMENT_TYPE_SKIP_SET */ },
	{ E_CONTACT_REV,		/* PidTagLastModificationTime,	ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_FILE_AS,		/* PidLidFileUnder,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_FULL_NAME,		/* PidTagDisplayName,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_GIVEN_NAME,		/* PidTagGivenName,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_FAMILY_NAME,	/* PidTagSurname,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_NICKNAME,		/* PidTagNickname,		ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_EMAIL_1,		/* PidLidEmail1OriginalDisplayName,ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_EMAIL_2,		/* PidLidEmail2EmailAddress,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_EMAIL_3,		/* PidLidEmail3EmailAddress,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_IM_AIM,		/* PidLidInstantMessagingAddress,	ELEMENT_TYPE_COMPLEX */ },

	{ E_CONTACT_PHONE_BUSINESS,	/* PidTagBusinessTelephoneNumber,	ELEMENT_TYPE_SIMPLE */},
	{ E_CONTACT_PHONE_HOME,		/* PidTagHomeTelephoneNumber,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_MOBILE,	/* PidTagMobileTelephoneNumber,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_HOME_FAX,	/* PidTagHomeFaxNumber,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_BUSINESS_FAX,	/* PidTagBusinessFaxNumber,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_PAGER,	/* PidTagPagerTelephoneNumber,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_ASSISTANT,	/* PidTagAssistantTelephoneNumber,ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_PHONE_COMPANY,	/* PidTagCompanyMainTelephoneNumber,ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_HOMEPAGE_URL,	/* PidLidHtml,			ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_FREEBUSY_URL,	/* PidLidFreeBusyLocation,	ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_ROLE,		/* PidTagProfession,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_TITLE,		/* PidTagTitle,			ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_ORG,		/* PidTagCompanyName,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_ORG_UNIT,		/* PidTagDepartmentName,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_MANAGER,		/* PidTagManagerName,		ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_ASSISTANT,		/* PidTagAssistant,		ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_OFFICE,		/* PidTagOfficeLocation,	ELEMENT_TYPE_SIMPLE */ },
	{ E_CONTACT_SPOUSE,		/* PidTagSpouseName,		ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_BIRTH_DATE,		/* PidTagBirthday,		ELEMENT_TYPE_COMPLEX */ },
	{ E_CONTACT_ANNIVERSARY,	/* PidTagWeddingAnniversary,	ELEMENT_TYPE_COMPLEX */ },

	{ E_CONTACT_NOTE,		/* PidTagBody,			ELEMENT_TYPE_SIMPLE */ },

	{ E_CONTACT_ADDRESS_HOME,	/* PidLidHomeAddress,		ELEMENT_TYPE_COMPLEX */ },
	{ E_CONTACT_ADDRESS_WORK,	/* PidLidOtherAddress,		ELEMENT_TYPE_COMPLEX */ }
};

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

gboolean
kolab_util_contact_has_id (EContact *contact)
{
	gchar *uid = NULL;

	g_assert (E_IS_CONTACT (contact));

	uid = (gchar *) e_contact_get (contact, E_CONTACT_UID);

	if (uid == NULL)
		return FALSE;

	g_free (uid);

	return TRUE;
}

void
kolab_util_contact_gen_uid_if_none (EContact **contact)
{
	gchar *uid = NULL;

	g_assert (E_IS_CONTACT (*contact));

	if (! kolab_util_contact_has_id (*contact)) {
		/* no uid yet */
		uid = e_cal_component_gen_uid ();
		e_contact_set (*contact, E_CONTACT_UID, (gconstpointer) uid);
	}

	g_free (uid);

}

gboolean
kolab_util_contact_store (EContact *econtact,
                          KolabMailAccess *koma,
                          const gchar *uri,
                          GCancellable *cancellable,
                          GError **error)
{
	const gchar *sourcename = NULL;
	KolabMailHandle *kmh = NULL;
	GError *tmp_error = NULL;
	gboolean ok = FALSE;

	g_assert (E_IS_CONTACT (econtact));
	g_assert (KOLAB_IS_MAIL_ACCESS (koma));
	g_assert (uri != NULL);
	/* cancellable may be NULL */
	g_return_val_if_fail (error == NULL || *error == NULL, FALSE);

	sourcename = kolab_util_backend_get_relative_path_from_uri (uri);

	kolab_util_backend_modtime_set_on_econtact (econtact);
	kmh = kolab_mail_handle_new_from_econtact (econtact);

	ok =  kolab_mail_access_store_handle (koma,
	                                      kmh,
	                                      sourcename,
	                                      cancellable,
	                                      &tmp_error);
	if (! ok) {
		g_propagate_error (error, tmp_error);
		return FALSE;
	}

	return TRUE;
} /* kolab_util_contact_store () */

#if 0
EBookBackendSyncStatus
kolab_util_contact_map_error (GError *error)
{
	EBookBackendSyncStatus status = GNOME_Evolution_Addressbook_Success;

	if (error == NULL)
		return GNOME_Evolution_Addressbook_Success;

	switch (error->code) {
	case KOLAB_BACKEND_ERROR_SYNC_NOTSTORED:
		status = GNOME_Evolution_Addressbook_Success;
		break;
	case KOLAB_BACKEND_ERROR_NOTFOUND:
		status = GNOME_Evolution_Addressbook_ContactNotFound;
		break;
	case KOLAB_BACKEND_ERROR_CONTEXT_MISUSE:
	case KOLAB_BACKEND_ERROR_INFODB_NOFOLDER:
		status = GNOME_Evolution_Addressbook_NoSuchBook;
		break;
	default:
		status = GNOME_Evolution_Addressbook_OtherError;
	}

	g_debug ("%s()[%u] EBookBackendSyncStatus: %i", __func__, __LINE__, status);
	return status;
}
#endif

void
kolab_util_contact_err_to_edb_err (GError **e_err,
                                   const GError *k_err,
                                   const gchar *func,
                                   guint line)
{
	EDataBookStatus status = E_DATA_BOOK_STATUS_OTHER_ERROR;
	GError *tmp_err = NULL;

	g_return_if_fail (e_err == NULL || *e_err == NULL);
	g_return_if_fail (k_err != NULL);

	g_warning ("%s()[%u]: '%s', Code %i, Domain '%s'",
	           func, line, k_err->message, k_err->code,
	           g_quark_to_string (k_err->domain));

	if (!e_err)
		return;

	if (g_error_matches (k_err, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
		g_propagate_error (e_err, g_error_copy (k_err));
		return;
	}

	/* TODO
	 *
	 * Need to implement a more elaborated error mapping here.
	 * This function maps Kolab engine errors only. Errors can
	 * originate from the camel/ as well as from the libekolab/
	 * libs. These yield errors in various domains. The following
	 * E_DATA_BOOK_STATUS_* (other than OTHER_ERROR) are candidates
	 * for being populated from certain k_err's:
	 *
	 * E_DATA_BOOK_STATUS_REPOSITORY_OFFLINE,
	 * E_DATA_BOOK_STATUS_PERMISSION_DENIED,
	 * E_DATA_BOOK_STATUS_CONTACT_NOT_FOUND,
	 * E_DATA_BOOK_STATUS_CONTACTID_ALREADY_EXISTS,
	 * E_DATA_BOOK_STATUS_AUTHENTICATION_FAILED,
	 * E_DATA_BOOK_STATUS_AUTHENTICATION_REQUIRED,
	 * E_DATA_BOOK_STATUS_NO_SUCH_BOOK,
	 * E_DATA_BOOK_STATUS_BOOK_REMOVED,
	 * E_DATA_BOOK_STATUS_SEARCH_SIZE_LIMIT_EXCEEDED,
	 * E_DATA_BOOK_STATUS_SEARCH_TIME_LIMIT_EXCEEDED,
	 * E_DATA_BOOK_STATUS_INVALID_QUERY,
	 * E_DATA_BOOK_STATUS_QUERY_REFUSED,
	 * E_DATA_BOOK_STATUS_COULD_NOT_CANCEL,
	 * E_DATA_BOOK_STATUS_INVALID_SERVER_VERSION,
	 * E_DATA_BOOK_STATUS_NO_SPACE,
	 * E_DATA_BOOK_STATUS_NOT_SUPPORTED,
	 *
	 * Depending on k_err->domain and k_err->code, we can map
	 * to a fitting E_DATA_BOOK_STATUS. More than one combination
	 * of k_err->domain and k_err->code may map to one specific
	 * E_DATA_BOOK_STATUS.
	 */

	tmp_err = e_data_book_create_error (status,
	                                    k_err->message);
	g_propagate_error (e_err, tmp_err);
}

/* return with g_slist_free(), 'data' pointers (strings) are not newly allocated */
GSList *
kolab_utils_contact_get_supported_fields (void)
{
	guint ii = 0;
	GSList *fields = NULL;

	for (ii = 0; ii < G_N_ELEMENTS (mappings); ii++) {
		fields = g_slist_append (fields, (gpointer) e_contact_field_name (mappings[ii].field_id));
	}

	fields = g_slist_append (fields, (gpointer) e_contact_field_name (E_CONTACT_BOOK_URI));

	return fields;
}

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