/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/***************************************************************************
 *            kolab-mail-summary.h
 *
 *  Fri Jan 28 10:05:23 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 <libical/ical.h>

#include <camel/camel-kolab-imapx-metadata.h>

#include <libekolabutil/kolab-util-folder.h>

#include "kolab-mail-summary.h"

/*----------------------------------------------------------------------------*/
/* local helpers */
static void
kolab_mail_summary_util_e_cal_component_free_text (ECalComponentText *ect)
{
	if (ect == NULL)
		return;
	g_free (ect);
}

static void
kolab_mail_summary_util_e_cal_component_free_organizer (ECalComponentOrganizer *eco)
{
	if (eco == NULL)
		return;
	g_free (eco);
}

/*----------------------------------------------------------------------------*/
/* new/free/check */

KolabMailSummary*
kolab_mail_summary_new (void)
{
	gint ii = 0;
	KolabMailSummary *summary = g_new0 (KolabMailSummary, 1);

	/* ECalComponent/EContact fields */
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++)
		summary->sdata_char[ii] = NULL;
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD; ii++)
		summary->sdata_uint[ii] = 0;
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD; ii++)
		summary->sdata_int[ii] = 0;
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD; ii++)
		summary->sdata_bool[ii] = FALSE;

	/* documenting folder context/type initial setting */
	summary->sdata_uint[KOLAB_MAIL_SUMMARY_UINT_FIELD_FOLDER_TYPE] = KOLAB_FOLDER_TYPE_INVAL;
	summary->sdata_uint[KOLAB_MAIL_SUMMARY_UINT_FIELD_FOLDER_CONTEXT] = KOLAB_FOLDER_CONTEXT_INVAL;

	return summary;
}

KolabMailSummary*
kolab_mail_summary_new_from_ecalcomponent (ECalComponent *ecalcomp)
{
	KolabMailSummary *summary = NULL;

	if (ecalcomp == NULL) {
		g_warning ("%s: ECalComponent is NULL, doing nothing", __func__);
		return NULL;
	}
	g_assert (E_IS_CAL_COMPONENT (ecalcomp));

	summary = kolab_mail_summary_new ();

	/* CHAR summary fields
	 *      If a field is unset in ECalComponent, it's KolabMailSummary
	 *      counterpart gets deleted (if it was set before)
	 */

	{ /* SUMMARY */
		ECalComponentText *ect = g_new0 (ECalComponentText, 1);
		e_cal_component_get_summary (ecalcomp, ect);
		kolab_mail_summary_set_char_field (summary,
		                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_SUMMARY,
		                                   g_strdup (ect->value));
		kolab_mail_summary_util_e_cal_component_free_text (ect);
	}

	{ /* ORGANIZER */
		ECalComponentOrganizer *eco = g_new0 (ECalComponentOrganizer, 1);
		e_cal_component_get_organizer (ecalcomp, eco);
		kolab_mail_summary_set_char_field (summary,
		                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_ORGANIZER,
		                                   g_strdup (eco->value));
		kolab_mail_summary_util_e_cal_component_free_organizer (eco);
	}

	{ /* LOCATION */
		const gchar *ecl = NULL;
		e_cal_component_get_location (ecalcomp, &ecl);
		kolab_mail_summary_set_char_field (summary,
		                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_LOCATION,
		                                   g_strdup (ecl));
	}

	{ /* CATEGORY */
		const gchar *ecc = NULL;
		e_cal_component_get_categories (ecalcomp, &ecc);
		kolab_mail_summary_set_char_field (summary,
		                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_CATEGORY,
		                                   g_strdup (ecc));
	}

	{ /* DTSTART */
		ECalComponentDateTime *ecdt = g_new0 (ECalComponentDateTime, 1);
		const gchar *dt = NULL;
		e_cal_component_get_dtstart (ecalcomp, ecdt);

		if (ecdt->value != NULL)
			dt = icaltime_as_ical_string (*(ecdt->value));

		if (dt != NULL) {
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTSTART,
			                                   g_strdup (dt));
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTSTART_TZID,
			                                   g_strdup (ecdt->tzid));
		} else {
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTSTART,
			                                   NULL);
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTSTART_TZID,
			                                   NULL);
		}
		e_cal_component_free_datetime (ecdt);
		g_free (ecdt);
	}

	{ /* DTEND */
		ECalComponentDateTime *ecdt = g_new0 (ECalComponentDateTime, 1);
		const gchar *dt = NULL;
		e_cal_component_get_dtend (ecalcomp, ecdt);

		if (ecdt->value != NULL)
			dt = icaltime_as_ical_string (*(ecdt->value));

		if (dt != NULL) {
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTEND,
			                                   g_strdup (dt));
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTEND_TZID,
			                                   g_strdup (ecdt->tzid));
		} else {
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTEND,
			                                   NULL);
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_DTEND_TZID,
			                                   NULL);
		}
		e_cal_component_free_datetime (ecdt);
		g_free (ecdt);
	}

	/* UINT summary fields
	 */

	{ /* CLASSIFICATION */
		ECalComponentClassification eccl = 0;
		e_cal_component_get_classification (ecalcomp, &eccl);
		kolab_mail_summary_set_uint_field (summary,
		                                   KOLAB_MAIL_SUMMARY_UINT_FIELD_E_CLASSIFICATION,
		                                   eccl);
	}


	{ /* STATUS */
		icalproperty_status istatus = 0;
		e_cal_component_get_status (ecalcomp, &istatus);
		kolab_mail_summary_set_uint_field (summary,
		                                   KOLAB_MAIL_SUMMARY_UINT_FIELD_E_STATUS,
		                                   istatus);
	}

	/* INT summary fields
	 */

	{ /* PRIORITY */
		gint *ecp = NULL;
		e_cal_component_get_priority (ecalcomp, &ecp);

		if (ecp != NULL) {
			kolab_mail_summary_set_int_field (summary,
			                                  KOLAB_MAIL_SUMMARY_INT_FIELD_E_PRIORITY,
			                                  *ecp);
			e_cal_component_free_priority (ecp);
		} else {
			kolab_mail_summary_set_int_field (summary,
			                                  KOLAB_MAIL_SUMMARY_INT_FIELD_E_PRIORITY,
			                                  0);
		}
	}

	{ /* PERCENT */
		gint *epc = NULL;
		e_cal_component_get_percent (ecalcomp, &epc);

		if (epc != NULL) {
			kolab_mail_summary_set_int_field (summary,
			                                  KOLAB_MAIL_SUMMARY_INT_FIELD_E_PERCENT,
			                                  *epc);
			e_cal_component_free_percent (epc);
		} else {
			kolab_mail_summary_set_int_field (summary,
			                                  KOLAB_MAIL_SUMMARY_INT_FIELD_E_PERCENT,
			                                  0);
		}
	}

	/* BOOL summary fields
	 */

	{ /* HAS_ATTENDEES */
		gboolean bval = FALSE;
		bval = e_cal_component_has_attendees (ecalcomp);
		kolab_mail_summary_set_bool_field (summary,
		                                   KOLAB_MAIL_SUMMARY_BOOL_FIELD_E_HAS_ATTENDEES,
		                                   bval);
	}

	{ /* HAS_ATTACHMENTS */
		gboolean bval = FALSE;
		bval = e_cal_component_has_attachments (ecalcomp);
		kolab_mail_summary_set_bool_field (summary,
		                                   KOLAB_MAIL_SUMMARY_BOOL_FIELD_E_HAS_ATTACHMENTS,
		                                   bval);
	}

	{ /* HAS_RECURRENCE */
		gboolean bval = FALSE;
		bval = e_cal_component_has_recurrences (ecalcomp);
		kolab_mail_summary_set_bool_field (summary,
		                                   KOLAB_MAIL_SUMMARY_BOOL_FIELD_E_HAS_RECURRENCE,
		                                   bval);
	}

	{ /* HAS_ALARMS */
		gboolean bval = FALSE;
		bval = e_cal_component_has_alarms (ecalcomp);
		kolab_mail_summary_set_bool_field (summary,
		                                   KOLAB_MAIL_SUMMARY_BOOL_FIELD_E_HAS_ALARMS,
		                                   bval);
	}

	return summary;
}

KolabMailSummary*
kolab_mail_summary_new_from_econtact (EContact *econtact)
{
	KolabMailSummary *summary = NULL;

	if (econtact == NULL) {
		g_warning ("%s: EContact is NULL, doing nothing", __func__);
		return NULL;
	}
	g_assert (E_IS_CONTACT (econtact));

	summary = kolab_mail_summary_new ();

	/* CHAR summary fields
	 *      If a field is unset in ECalComponent, it's KolabMailSummary
	 *      counterpart gets deleted (if it was set before)
	 */

	{ /* FULLNAME */
		gconstpointer gp = e_contact_get_const (econtact,
		                                        E_CONTACT_FULL_NAME);
		if (gp != NULL)
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_FULLNAME,
			                                   g_strdup ((const gchar*)gp));
		else
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_FULLNAME,
			                                   NULL);
	}

	{ /* EMAIL */
		guint evo_field_ids[] = {E_CONTACT_EMAIL_1, E_CONTACT_EMAIL_2, E_CONTACT_EMAIL_3, E_CONTACT_EMAIL_4};
		guint sum_field_ids[] = {KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_EMAIL_1, KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_EMAIL_2, KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_EMAIL_3, KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_EMAIL_4};
		gconstpointer gp = NULL;
		gint ii = 0;
		for (ii = 0; ii < 4; ii++) {
			gp = e_contact_get_const (econtact, evo_field_ids[ii]);
			if (gp != NULL)
				kolab_mail_summary_set_char_field (summary,
				                                   sum_field_ids[ii],
				                                   g_strdup ((const gchar*)gp));
			else
				kolab_mail_summary_set_char_field (summary,
				                                   sum_field_ids[ii],
				                                   NULL);
		}
	}

	{ /* CATEGORY */
		gconstpointer gp = e_contact_get_const (econtact,
		                                        E_CONTACT_CATEGORIES);
		if (gp != NULL)
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_CATEGORY,
			                                   g_strdup ((const gchar*)gp));
		else
			kolab_mail_summary_set_char_field (summary,
			                                   KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_CATEGORY,
			                                   NULL);
	}

	return summary;
}

KolabMailSummary*
kolab_mail_summary_clone (const KolabMailSummary *summary)
{
	KolabMailSummary *new_summary = NULL;
	gint ii = 0;

	if (summary == NULL)
		return NULL;

	new_summary = g_new0 (KolabMailSummary, 1);

	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++)
		new_summary->sdata_char[ii] = g_strdup (summary->sdata_char[ii]);
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD; ii++)
		new_summary->sdata_uint[ii] = summary->sdata_uint[ii];
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD; ii++)
		new_summary->sdata_int[ii] = summary->sdata_int[ii];
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD; ii++)
		new_summary->sdata_bool[ii] = summary->sdata_bool[ii];

	return new_summary;
}

void
kolab_mail_summary_update_eds_data (KolabMailSummary *summary,
                                    const KolabMailSummary *src_summary)
{
	gint ii = 0;

	g_assert (summary != NULL);
	g_assert (src_summary != NULL);

	/* update char fields */
	for (ii = KOLAB_MAIL_SUMMARY_CHAR_FIELD_E_SUMMARY; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++) {
		if (summary->sdata_char[ii] != NULL)
			g_free (summary->sdata_char[ii]);
		summary->sdata_char[ii] = g_strdup (src_summary->sdata_char[ii]);
	}

	/* update uint fields */
	for (ii = KOLAB_MAIL_SUMMARY_UINT_FIELD_E_CLASSIFICATION; ii < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD; ii++)
		summary->sdata_uint[ii] = src_summary->sdata_uint[ii];

	/* update int fields */
	for (ii = KOLAB_MAIL_SUMMARY_INT_FIELD_E_PRIORITY; ii < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD; ii++)
		summary->sdata_int[ii] = src_summary->sdata_int[ii];

	/* update bool fields */
	for (ii = KOLAB_MAIL_SUMMARY_BOOL_FIELD_E_HAS_ATTENDEES; ii < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD; ii++)
		summary->sdata_bool[ii] = src_summary->sdata_bool[ii];

}


void
kolab_mail_summary_free (KolabMailSummary *summary)
{
	gint ii = 0;

	if (summary == NULL)
		return;

	/* ECalComponent/EContact fields */
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++) {
		if (summary->sdata_char[ii] != NULL)
			g_free (summary->sdata_char[ii]);
	}

	g_free (summary);
}

void
kolab_mail_summary_gdestroy (gpointer data)
{
	KolabMailSummary *summary = NULL;

	if (data == NULL)
		return;

	summary = (KolabMailSummary *)data;
	kolab_mail_summary_free (summary);
}

gboolean
kolab_mail_summary_check (const KolabMailSummary *summary)
{
	KolabFolderContextID folder_context;

	if (summary == NULL) {
		g_warning ("%s: summary is NULL",
		           __func__);
		return FALSE;
	}

	/* map folder type to folder context */
	folder_context = kolab_util_folder_type_map_to_context_id (summary->sdata_uint[KOLAB_MAIL_SUMMARY_UINT_FIELD_FOLDER_TYPE]);
	if (folder_context == KOLAB_FOLDER_CONTEXT_INVAL) {
		g_warning ("%s: KolabFolderMetaTypeID does not map to any KolabFolderContextID",
		           __func__);
		return FALSE;
	}
	if (summary->sdata_uint[KOLAB_MAIL_SUMMARY_UINT_FIELD_FOLDER_CONTEXT] != folder_context) {
		g_warning ("%s: KolabFolderMetaTypeID/KolabFolderContextID inconsistency detected",
		           __func__);
		return FALSE;
	}

	/* check Kolab UID */
	if (summary->sdata_char[KOLAB_MAIL_SUMMARY_CHAR_FIELD_KOLAB_UID] == NULL) {
		g_warning ("%s: Kolab UID not set",
		           __func__);
		return FALSE;
	}

	/* TODO more consistency checks? */

	return TRUE;
}

gboolean
kolab_mail_summary_equal (const KolabMailSummary *summary1,
                          const KolabMailSummary *summary2)
{
	guint ii = 0;

	if ((summary1 == NULL) && (summary2 == NULL))
		return TRUE;
	if ((summary1 == NULL) && (summary2 != NULL))
		return FALSE;
	if ((summary1 != NULL) && (summary2 == NULL))
		return FALSE;

	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++) {
		if (g_strcmp0 (summary1->sdata_char[ii], summary2->sdata_char[ii]) != 0)
			return FALSE;
	}
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD; ii++) {
		if (summary1->sdata_uint[ii] != summary2->sdata_uint[ii])
			return FALSE;
	}
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD; ii++) {
		if (summary1->sdata_int[ii] != summary2->sdata_int[ii])
			return FALSE;
	}
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD; ii++) {
		if (summary1->sdata_bool[ii] != summary2->sdata_bool[ii])
			return FALSE;
	}

	return TRUE;
}

/*----------------------------------------------------------------------------*/
/* getters/setters */

void
kolab_mail_summary_set_char_field (KolabMailSummary *summary,
                                   KolabMailSummaryCharFieldID field_id,
                                   gchar *value)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD);

	if (summary->sdata_char[field_id] != NULL)
		g_free (summary->sdata_char[field_id]);

	summary->sdata_char[field_id] = value; /* no copy! */
}

const gchar*
kolab_mail_summary_get_char_field (const KolabMailSummary *summary,
                                   KolabMailSummaryCharFieldID field_id)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD);

	return summary->sdata_char[field_id]; /* no copy! */
}

void
kolab_mail_summary_set_uint_field (KolabMailSummary *summary,
                                   KolabMailSummaryUintFieldID field_id,
                                   guint value)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD);

	summary->sdata_uint[field_id] = value;
}

guint
kolab_mail_summary_get_uint_field (const KolabMailSummary *summary,
                                   KolabMailSummaryUintFieldID field_id)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD);

	return summary->sdata_uint[field_id];
}

void
kolab_mail_summary_set_int_field (KolabMailSummary *summary,
                                  KolabMailSummaryIntFieldID field_id,
                                  gint value)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD);

	summary->sdata_int[field_id] = value;
}

gint
kolab_mail_summary_get_int_field (const KolabMailSummary *summary,
                                  KolabMailSummaryIntFieldID field_id)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD);

	return summary->sdata_int[field_id];
}

void
kolab_mail_summary_set_bool_field (KolabMailSummary *summary,
                                   KolabMailSummaryBoolFieldID field_id,
                                   gboolean value)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD);

	summary->sdata_bool[field_id] = value;
}

gboolean
kolab_mail_summary_get_bool_field (const KolabMailSummary *summary,
                                   KolabMailSummaryBoolFieldID field_id)
{
	g_assert (summary != NULL);
	g_assert (field_id < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD);

	return summary->sdata_bool[field_id];
}

/*----------------------------------------------------------------------------*/
/* DEBUG */

void
kolab_mail_summary_debug_print (const KolabMailSummary *summary)
{
	gint ii;
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_CHAR_LAST_FIELD; ii++)
		g_debug ("%s", kolab_mail_summary_get_char_field (summary, ii));
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_UINT_LAST_FIELD; ii++)
		g_debug ("%i", kolab_mail_summary_get_uint_field (summary, ii));
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_INT_LAST_FIELD; ii++)
		g_debug ("%i", kolab_mail_summary_get_int_field (summary, ii));
	for (ii = 0; ii < KOLAB_MAIL_SUMMARY_BOOL_LAST_FIELD; ii++)
		g_debug ("%i", kolab_mail_summary_get_bool_field (summary, ii));
}

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