/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
 * priv-incidence-k-to-i.c
 *
 *  Created on: 30.09.2010
 *      Author: Hendrik Helwich <h.helwich@tarent.de>,
 *              Umer Kayani <u.kayani@tarent.de>,
 *              Peter Neuhaus <p.neuhaus@tarent.de>,
 *              Andreas Grau <a.grau@tarent.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
 */

/*
 * This file holds operations to read the kolab incidence fields from an XML
 * tree to an internal structure.
 *
 * The related header file is: k-abstract.h
 */

#include "priv-kolab.h"		/* public part of this file */
#include "../util.h"
#include <libxml/tree.h>	/* XML parsing */

/*
 * prototypes for static functions
 */
static Alarm_type alarm_type_k_to_i(gchar *k_alarm_type);
static Month month_k_to_i (const gchar *k_month);
static Incidence_role incidence_role_k_to_i (const gchar *k_incidence_role);
static Incidence_status incidence_status_k_to_i (const gchar *k_incidence_status);
static Week_day weekday_k_to_i (const gchar *weekday_str);
static gboolean handle_incidence_alarm(I_incidence *incidence, xmlNodePtr node);
static gboolean handle_incidence_advanced_alarm (I_incidence *incidence, xmlNodePtr node);
static Recurrence_cycle handle_incidence_recurrence_cycle (xmlNodePtr node);
static gboolean handle_incidence_recurrence_weekdays (guint *weekdays, xmlNodePtr node);
static gboolean handle_incidence_recurrence_month (Month *month, xmlNodePtr node);
static gboolean handle_incidence_recurrence_exclusion (GList **exclusion_list, xmlNodePtr node);
static gboolean handle_incidence_recurrence_range (GDate **rdate, gint **rnumber, xmlNodePtr node);
static gboolean handle_incidence_recurrence (I_incidence *incidence, xmlNodePtr node);
static gboolean handle_incidence_attendee(I_incidence *incidence, xmlNodePtr node);
static gboolean handle_incidence_organizer (I_incidence *i_incidence, xmlNodePtr node);


/**
 * Converts the data of a Kolab XML sub-root-node to an internal incidence
 * structure if the XML node is a Kolab common or incidence node.
 *
 * @param  i_incidence
 *         an internal incidence structure
 * @param  node
 *         a Kolab XML sub-root-node
 * @param  error
 *         A pointer to a NULL error object pointer which will be filled if an
 *         error occurs. It must be checked after calling this operation.
 * @return TRUE if the given kolab XML node is a Kolab common or incidence node
 *         and no error has occured.
 */
gboolean
conv_incidence_k_to_i(I_incidence *i_incidence, xmlNodePtr node, GError **error)
{
	if (common_k_to_i(i_incidence->common, node, error))
		return TRUE;
	else if (*error != NULL)
		return FALSE;

	return	handle_element_string(KLB_INC_SUMMARY, &i_incidence->summary, node) ||				/* summary */
		handle_element_string(KLB_INC_LOCATION, &i_incidence->location, node) ||			/* location */
		handle_incidence_organizer(i_incidence, node) ||						/* organizer */
		handle_element_date_or_datetime(KLB_INC_START_DATE, &i_incidence->start_date, node) ||		/* start-date */
		handle_incidence_alarm(i_incidence, node) ||							/* alarm */
		handle_incidence_advanced_alarm(i_incidence, node) ||						/* advanced_alarm */
		handle_incidence_recurrence(i_incidence, node) ||						/* recurrence */
		handle_incidence_attendee(i_incidence, node);							/* attendee */
}


/**
 * Mapping type of alarm from Kolab type to intern structure type
 */
static Alarm_type
alarm_type_k_to_i(gchar *k_alarm_type)
{
	if (strcmp(k_alarm_type, KLBX_INC_ADV_ALARM_TYPE_DISPLAY) == 0)
		return I_ALARM_TYPE_DISPLAY;
	if (strcmp(k_alarm_type, KLBX_INC_ADV_ALARM_TYPE_AUDIO) == 0)
		return I_ALARM_TYPE_AUDIO;
	if (strcmp(k_alarm_type, KLBX_INC_ADV_ALARM_TYPE_PROCEDURE) == 0)
		return I_ALARM_TYPE_PROCEDURE;
	if (strcmp(k_alarm_type, KLBX_INC_ADV_ALARM_TYPE_EMAIL) == 0)
		return I_ALARM_TYPE_EMAIL;

	return I_ALARM_TYPE_DISPLAY;
}

/**
 * Mapping month from Kolab type to intern structure type
 *
 * There is one special bug handling case for august, because Toltec writes "agust" intead of "august".
 */
static Month
month_k_to_i (const gchar *k_month)
{
	if (strcmp (k_month, KLB_INC_RCR_MONTH_JAN) == 0)
		return I_COMMON_JAN;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_FEB) == 0)
		return I_COMMON_FEB;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_MAR) == 0)
		return I_COMMON_MAR;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_APR) == 0)
		return I_COMMON_APR;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_MAY) == 0)
		return I_COMMON_MAY;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_JUN) == 0)
		return I_COMMON_JUN;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_JUL) == 0)
		return I_COMMON_JUL;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_AUG) == 0)
		return I_COMMON_AUG;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_AUG_TOLTEC) == 0)
		return I_COMMON_AUG;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_SEP) == 0)
		return I_COMMON_SEP;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_OCT) == 0)
		return I_COMMON_OCT;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_NOV) == 0)
		return I_COMMON_NOV;
	if (strcmp (k_month, KLB_INC_RCR_MONTH_DEC) == 0)
		return I_COMMON_DEC;

	return -1;
}

/**
 * Mapping of attendee role for tasks and events from Kolab to intern.
 */
static Incidence_role
incidence_role_k_to_i (const gchar *k_incidence_role)
{
	if (strcmp (k_incidence_role, KLB_INC_ATTENDEE_ROLE_REQUIRED) == 0)
		return I_INC_ROLE_REQUIRED;
	if (strcmp (k_incidence_role, KLB_INC_ATTENDEE_ROLE_OPTIONAL) == 0)
		return I_INC_ROLE_OPTIONAL;
	if (strcmp (k_incidence_role, KLB_INC_ATTENDEE_ROLE_RESOURCE) == 0)
		return I_INC_ROLE_RESOURCE;

	return I_INC_ROLE_REQUIRED;
}

/**
 * Mapping of attendee cutype for tasks and events from Kolab to intern.
 */
static Incidence_cutype
incidence_cutype_k_to_i (const gchar *k_incidence_cutype)
{
	if (strcmp (k_incidence_cutype, KLBC_INCIDENCE_ATTENDEE_TYPE_INDIVIDUAL) == 0)
		return I_INC_CUTYPE_INDIVIDUAL;
	if (strcmp (k_incidence_cutype, KLBC_INCIDENCE_ATTENDEE_TYPE_GROUP) == 0)
		return I_INC_CUTYPE_GROUP;
	if (strcmp (k_incidence_cutype, KLBC_INCIDENCE_ATTENDEE_TYPE_RESOURCE) == 0)
		return I_INC_CUTYPE_RESOURCE;
	if (strcmp (k_incidence_cutype, KLBC_INCIDENCE_ATTENDEE_TYPE_ROOM) == 0)
		return I_INC_CUTYPE_ROOM;
	return I_INC_CUTYPE_UNDEFINED;
}

/**
 * Mapping of attendee status for events and tasks from Kolab to intern.
 */
static Incidence_status
incidence_status_k_to_i (const gchar *k_incidence_status)
{
	if (strcmp (k_incidence_status, KLB_INC_ATTENDEE_STATUS_NONE) == 0)
		return I_INC_STATUS_NONE;
	if (strcmp (k_incidence_status, KLB_INC_ATTENDEE_STATUS_TENTATIVE) == 0)
		return I_INC_STATUS_TENTATIVE;
	if (strcmp (k_incidence_status, KLB_INC_ATTENDEE_STATUS_ACCEPTED) == 0)
		return I_INC_STATUS_ACCEPTED;
	if (strcmp (k_incidence_status, KLB_INC_ATTENDEE_STATUS_DECLINED) == 0)
		return I_INC_STATUS_DECLINED;
	if (strcmp (k_incidence_status, KLBX_INC_ATTENDEE_STATUS_DELEGATED) == 0)
		return I_INC_STATUS_DELEGATED;

	return I_INC_STATUS_NONE;
}


/**
 * Parse the text content of a kolab day node and return the related element
 * of the RecurrenceDay enumeration or 0 if the given string is unknown.
 *
 * @param  weekday_str
 *         The text content of a kolab recurrence day node
 * @return An element of the RecurrenceDay enumeration or 0 if the given string
 *         is unknown
 */
static Week_day
weekday_k_to_i (const gchar *weekday_str)
{
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_MONDAY) == 0)
		return I_COMMON_MONDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_TUESDAY) == 0)
		return I_COMMON_TUESDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_WEDNESDAY) == 0)
		return I_COMMON_WEDNESDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_THURSDAY) == 0)
		return I_COMMON_THURSDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_FRIDAY) == 0)
		return I_COMMON_FRIDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_SATURDAY) == 0)
		return I_COMMON_SATURDAY;
	if (strcmp (weekday_str, KLB_INC_RCR_DAY_SUNDAY) == 0)
		return I_COMMON_SUNDAY;

	log_warn("unknown kolab weekday string %s", weekday_str);
	return I_COMMON_NO_DAY;
}

/**
 * Function sets Advanced Alarm from normal Alarm.
 *
 * Intern only Advanced Alarms are saved and the first Advanced Alarm in the
 * special case of a simple Alarm is converted back.
 */
static gboolean
handle_incidence_alarm(I_incidence *incidence, xmlNodePtr node)
{
	if (strcmp ((gchar *) node->name, KLB_INC_ALARM) != 0)
		return FALSE;

	if (node->type == XML_ELEMENT_NODE) { /* Alarm_type type */
		Alarm *adv_alarm = new_alarm(alarm_type_k_to_i("KLBX_INC_ADV_ALARM_TYPE_DISPLAY_TEXT"));

		/* start_offset */
		handle_element_integer(KLB_INC_ALARM, &adv_alarm->start_offset, node);

		/* add advanced_alarm to list */
		incidence->advanced_alarm = g_list_append(incidence->advanced_alarm, (gpointer) adv_alarm);
	}
	return TRUE;
}

/**
 * Checks if the given XML element node is an advanced_alarm node and adds the alarm
 * to the given advanced_alarm.
 *
 * @param  advanced_alarm
 * @param  node
 * @return TRUE if the XML node is an exclusion node
 */
static gboolean
handle_incidence_advanced_alarm (I_incidence *incidence, xmlNodePtr node)
{
	xmlNodePtr alarm_node = NULL; /* used in for loop */

	if (strcmp ((gchar *) node->name, KLBX_INC_ADV_ALARM) != 0)
		return FALSE;

	for (alarm_node = node->children; alarm_node != NULL; alarm_node = alarm_node->next) {
		if (alarm_node->type == XML_ELEMENT_NODE) {

			if (strcmp ((gchar *) alarm_node->name, KLB_INC_ALARM) == 0) {
				xmlNodePtr alarm_attribute = NULL; /* used in for loop */
				gchar *type = (gchar *) xmlGetProp (alarm_node, (xmlChar *) KLBX_INC_ADV_ALARM_TYPE);
				Alarm *adv_alarm = new_alarm(alarm_type_k_to_i(type));
				g_free(type);

				for (alarm_attribute = alarm_node->children; alarm_attribute != NULL; alarm_attribute = alarm_attribute->next) {

					if (alarm_attribute->type == XML_ELEMENT_NODE) {
						/* handle advanced alarm type dependent attributes */
						gboolean handled = FALSE;
						if (adv_alarm->type == I_ALARM_TYPE_DISPLAY) {
							handled  = handle_element_string(KLBX_INC_ADV_ALARM_TYPE_DISPLAY_TEXT, &adv_alarm->display_text, alarm_attribute);
						} else if (adv_alarm->type == I_ALARM_TYPE_AUDIO) {
							handled  = handle_element_string(KLBX_INC_ADV_ALARM_TYPE_AUDIO_FILE, &adv_alarm->audio_file, alarm_attribute);
						} else if (adv_alarm->type == I_ALARM_TYPE_PROCEDURE) {
							handled  = handle_element_string(KLBX_INC_ADV_ALARM_TYPE_PROCEDURE_PROGRAM, &adv_alarm->proc_param->program, alarm_attribute);
							handled |= handle_element_string(KLBX_INC_ADV_ALARM_TYPE_PROCEDURE_ARGUMENTS, &adv_alarm->proc_param->arguments, alarm_attribute);
						} else if (adv_alarm->type == I_ALARM_TYPE_EMAIL) {
							handled  = handle_element_GList_String(KLBX_INC_ADV_ALARM_TYPE_EMAIL_ADDRESSES, KLBX_INC_ADV_ALARM_TYPE_EMAIL_ADDRESSES_ADDRESS, &adv_alarm->email_param->addresses, alarm_attribute);
							handled |= handle_element_string(KLBX_INC_ADV_ALARM_TYPE_EMAIL_SUBJECT, &adv_alarm->email_param->subject, alarm_attribute);
							handled |= handle_element_string(KLBX_INC_ADV_ALARM_TYPE_EMAIL_MAIL_TEXT, &adv_alarm->email_param->mail_text, alarm_attribute);
							handled |= handle_element_GList_String(KLBX_INC_ADV_ALARM_TYPE_EMAIL_ATTACHMENTS, KLBX_INC_ADV_ALARM_TYPE_EMAIL_ATTACHMENTS_ATT, &adv_alarm->email_param->attachments, alarm_attribute);
						}

						/* handle advanced alarm common attributes */
						if (strcmp ((gchar *) alarm_attribute->name, KLBX_INC_ADV_ALARM_START_OFFSET) == 0) {					/* start_offset */
							handle_element_integer(KLBX_INC_ADV_ALARM_START_OFFSET, &adv_alarm->start_offset, alarm_attribute);
						} else if (strcmp ((gchar *) alarm_attribute->name, KLBX_INC_ADV_ALARM_END_OFFSET) == 0) {				/* end_offset */
							handle_element_integer(KLBX_INC_ADV_ALARM_END_OFFSET, &adv_alarm->end_offset, alarm_attribute);
						} else if (strcmp ((gchar *) alarm_attribute->name, KLBX_INC_ADV_ALARM_REPEAT_COUNT) == 0) {				/* repeat_count */
							handle_element_integer(KLBX_INC_ADV_ALARM_REPEAT_COUNT, &adv_alarm->repeat_count, alarm_attribute);
						} else if (strcmp ((gchar *) alarm_attribute->name, KLBX_INC_ADV_ALARM_REPEAT_INTERVAL) == 0) {				/* repeat_interval */
							handle_element_integer(KLBX_INC_ADV_ALARM_REPEAT_INTERVAL, &adv_alarm->repeat_interval, alarm_attribute);
						} else if (strcmp ((gchar *) alarm_attribute->name, KLBX_INC_ADV_ALARM_TYPE_EMAIL_ADDRESSES) == 0) {
						} else if (!handled)
							i_kolab_store_add_xml_element(incidence->common, adv_alarm, alarm_attribute);
					}

				}
				/* add advanced_alarm to list */
				incidence->advanced_alarm = g_list_append(incidence->advanced_alarm, (gpointer) adv_alarm);
			}
		}
	}

	return TRUE;
}



/**
 * Returns the recurrence cycle enum value for the given recurrence XML node.
 *
 * @param  node
 *         The recurrence kolab xml node
 * @return The recurrence cycle ebum value for the given recurrence XML node or
 *         -1 if the cycle cannot be determined
 */
static Recurrence_cycle
handle_incidence_recurrence_cycle (xmlNodePtr node)
{
	Recurrence_cycle cycle = I_REC_CYCLE_NULL;
	gchar *rcycle = (gchar *) xmlGetProp (node, (xmlChar *) KLB_INC_RCR_CYCLE);

	if (rcycle != NULL) {
		if (strcmp (rcycle, KLB_INC_RCR_CYCLE_MONTHLY) == 0) {
			gchar *rtype = (gchar *) xmlGetProp (node, (xmlChar *) KLB_INC_RCR_CYCLETYPE);
			if (strcmp (rtype, KLB_INC_RCR_CYCLETYPE_DAYNUMBER) == 0)
				cycle = I_REC_CYCLE_MONTHLY_DAYNUMBER;
			else if (strcmp (rtype, KLB_INC_RCR_CYCLETYPE_WEEKDAY) == 0)
				cycle = I_REC_CYCLE_MONTHLY_WEEKDAY;
			xmlFree(rtype);
		} else if (strcmp (rcycle, KLB_INC_RCR_CYCLE_YEARLY) == 0) {
			gchar *rtype = (gchar *) xmlGetProp (node, (xmlChar *) KLB_INC_RCR_CYCLETYPE);
			if (strcmp (rtype, KLB_INC_RCR_CYCLETYPE_MONTHDAY) == 0)
				cycle = I_REC_CYCLE_YEARLY_MONTHDAY;
			else if (strcmp (rtype, KLB_INC_RCR_CYCLETYPE_YEARDAY) == 0)
				cycle = I_REC_CYCLE_YEARLY_YEARDAY;
			else if (strcmp (rtype, KLB_INC_RCR_CYCLETYPE_WEEKDAY) == 0)
				cycle = I_REC_CYCLE_YEARLY_WEEKDAY;
			xmlFree(rtype);
		} else if (strcmp (rcycle, KLB_INC_RCR_CYCLE_DAILY) == 0) {
			cycle = I_REC_CYCLE_DAILY;
		} else if (strcmp (rcycle, KLB_INC_RCR_CYCLE_WEEKLY) == 0) {
			cycle = I_REC_CYCLE_WEEKLY;
		} else {
			log_warn("recurrence cycle cannot be determined");
		}
		xmlFree(rcycle);
	}

	return cycle;
}
/**
 * Checks if the given XML element node is a day node and adds the value of the
 * day to the given weekday bitset.
 *
 * @param  weekdays
 * @param  node
 * @return TRUE if the XML node is a day node
 */
static gboolean
handle_incidence_recurrence_weekdays (guint *weekdays, xmlNodePtr node)
{
	gchar *value = NULL;

	if (strcmp ((gchar *) node->name, KLB_INC_RCR_DAY) != 0)
		return FALSE;

	value = xml_get_node_text(node);
	*weekdays |= weekday_k_to_i(value);
	return TRUE;
}

/**
 * Checks if the given XML element node is a recurrence month node and assigns
 * the value to the given month parameter.
 *
 * @param  month
 * @param  node
 * @return TRUE if the XML node is a recurrence month node
 */
static gboolean
handle_incidence_recurrence_month (Month *month, xmlNodePtr node)
{
	gchar *value = NULL;

	if (strcmp ((gchar *) node->name, KLB_INC_RCR_MONTH) != 0)
		return FALSE;

	value = xml_get_node_text(node);
	*month = month_k_to_i(value);
	return TRUE;
}

/**
 * Checks if the given XML element node is a recurrence exclusion node and adds
 * the value to the exclusion list if this is true.
 *
 * @param  exclusion_list
 * @param  node
 * @return TRUE if the XML node is a recurrence exclusion node
 */
static gboolean
handle_incidence_recurrence_exclusion (GList **exclusion_list, xmlNodePtr node)
{
	gchar *value = NULL;
	GDate *date = NULL;

	if (strcmp ((gchar *) node->name, KLB_INC_RCR_EXCLUSION) != 0)
		return FALSE;

	value = xml_get_node_text(node);
	date = string_to_g_date(value);
	*exclusion_list = g_list_append(*exclusion_list, date);
	return TRUE;
}


/**
 * Checks if the given XML element node is a recurrence range node and adds the
 * value to the rdate or to the rnumber parameter depending on the range type
 * attribute of the given node.
 *
 * @param  rdate
 * @param  rnumber
 * @param  node
 * @return TRUE if the XML node is a recurrence range node
 */
static gboolean
handle_incidence_recurrence_range (GDate **rdate, gint **rnumber, xmlNodePtr node)
{
	gchar *rtype = NULL;

	if (strcmp ((gchar *) node->name, KLB_INC_RCR_RANGE) != 0)
		return FALSE;


	rtype = (gchar *) xmlGetProp (node, (xmlChar *) KLB_INC_RCR_RANGETYPE);
	if (rtype != NULL) {

		gchar *value = xml_get_node_text(node);

		if (*rdate != NULL || *rnumber != NULL) {
			log_warn("multiple assignment of recurrence range");
			*rdate = NULL;
			*rnumber = NULL;
		}

		if (strcmp (rtype, KLB_INC_RCR_RANGETYPE_NUMBER) == 0) {
			*rnumber = g_new0(gint, 1);
			**rnumber = strtol(value, &value, 10);
		} else if (strcmp (rtype, KLB_INC_RCR_RANGETYPE_DATE) == 0)
			*rdate = string_to_g_date(value);
		else
			log_warn("recurrence range cannot be determined");

		xmlFree(rtype);
	}

	return TRUE;
}

/**
 * Checks if the given XML element node is a recurrence node and adds the
 * content to a new recurrence structure inside of the given internal incidence
 * structure
 *
 * @param  incidence
 *         a recurrence structure will be added to this structure if the given
 *         kolab XML node is a recurrence node
 * @param  node
 *         a Kolab XML node
 * @return TRUE if the XML node is a recurrence node
 */
static gboolean
handle_incidence_recurrence (I_incidence *incidence, xmlNodePtr node)
{
	xmlNodePtr n = NULL; /* used in for loop */

	if (strcmp ((gchar*) node->name, KLB_INC_RECURRENCE) != 0)
		return FALSE;

	/* recurrence struct ptr is expected NULL. If not, maybe the element
	 * unexpectedly occurs multiple times => warn and reassign
	 */
	if (incidence->recurrence != NULL) {
		log_warn("multiple assignment of recurrence");
		g_free(incidence->recurrence);
	}

	incidence->recurrence = new_recurrence ();
	incidence->recurrence->recurrence_cycle = handle_incidence_recurrence_cycle(node);

	/* iterate over all child elements of node an process them */
	for (n = node->children; n != NULL; n = n->next) {
		if (n->type == XML_ELEMENT_NODE) {
			if (handle_incidence_recurrence_weekdays((guint *) &incidence->recurrence->weekdays, n)
			    || handle_element_integer(KLB_INC_RCR_DAYNUMBER, &incidence->recurrence->day_number, n)
			    || handle_incidence_recurrence_exclusion(&incidence->recurrence->exclusion, n)
			    || handle_element_integer(KLB_INC_RCR_INTERVAL, &incidence->recurrence->interval, n)
			    || handle_incidence_recurrence_range(&incidence->recurrence->range_date, &incidence->recurrence->range_number, n)
			    || handle_incidence_recurrence_month(&incidence->recurrence->month, n))
				continue;

			i_kolab_store_add_xml_element(incidence->common, (gpointer) KOLAB_STORE_PTR_INC_RECURRENCE, n);
		}
	}
	return TRUE;
}

/**
 * Handling of attendees. For every attendee tag in xml-tree from Kolab
 * a new intern object is created. All fields are set and complete object
 * appended to a intern list of attendees.
 */
static gboolean
handle_incidence_attendee(I_incidence *incidence, xmlNodePtr node)
{
	Attendee *attendee = NULL;
	xmlNodePtr n = NULL; /* used in for loop */

	if (strcmp ((gchar*) node->name, KLB_INC_ATTENDEE) != 0)
		return FALSE;

	attendee = g_new0(Attendee, 1);

	for (n = node->children; n != NULL; n = n->next) {
		if (n->type == XML_ELEMENT_NODE) {
			if (strcmp ((gchar *) n->name, KLB_INC_DISPLAY_NAME) == 0) {
				gchar *value = xml_get_node_text(n);
				attendee->display_name = g_string_new(value);
			} else if (strcmp ((gchar *) n->name, KLB_INC_SMTP_ADDRESS) == 0) {
				gchar *value = xml_get_node_text(n);
				attendee->smtp_address = g_string_new(value);
			} else if (strcmp ((gchar *) n->name, KLB_INC_ATTENDEE_STATUS) == 0) {
				gchar *value = xml_get_node_text(n);
				attendee->status = incidence_status_k_to_i(value);
			} else if (strcmp ((gchar *) n->name, KLB_INC_ATTENDEE_REQUEST_RESPONSE) == 0) {
				attendee->request_response = xml_get_boolean(n);
			} else if (strcmp ((gchar *) n->name, KLBX_INC_ATTENDEE_INVITATION_SENT) == 0) {
				attendee->invitation_sent = xml_get_boolean(n);
			} else if (strcmp ((gchar *) n->name, KLB_INC_ATTENDEE_ROLE) == 0) {
				gchar *value = xml_get_node_text(n);
				attendee->role = incidence_role_k_to_i(value);
			} else if (strcmp ((gchar *) n->name, KLBC_INCIDENCE_ATTENDEE_TYPE) == 0) {
				gchar *value = xml_get_node_text(n);
				attendee->cutype = incidence_cutype_k_to_i(value);
			} else {
				i_kolab_store_add_xml_element(incidence->common, attendee, n);
			}
		}
	}
	xmlFree(n);
	/* add attendee to list */
	incidence->attendee = g_list_append(incidence->attendee, (gpointer) attendee);

	return TRUE;
}

/**
 * Handling of event/task organizer. Contains two elements, name and e-mail/smtp-address.
 *
 * Unknown elements below organizer tag will be added to kolab store.
 */
static gboolean
handle_incidence_organizer (I_incidence *i_incidence, xmlNodePtr node)
{
	xmlNodePtr n = NULL; /* used in for loop */

	if (strcmp ((gchar*) node->name, KLB_INC_ORGANIZER) != 0)
		return FALSE;
	/* iterate over all child elements of node an process them */
	for (n = node->children; n != NULL; n = n->next) {
		if (n->type == XML_ELEMENT_NODE) {
			if (handle_element_string(KLB_INC_DISPLAY_NAME, &i_incidence->organizer_display_name, n)
			    || handle_element_string(KLB_INC_SMTP_ADDRESS, &i_incidence->organizer_smtp_address, n))
				continue;

			i_kolab_store_add_xml_element(i_incidence->common, (gpointer) KOLAB_STORE_PTR_INC_ORGANIZER, n);
		}
	}
	xmlFree(n);
	return TRUE;
}
