/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
 * event-k-to-i.c
 *
 *  Created on: 29.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 event fields from an XML tree
 * to an internal structure.
 *
 * The related header file is: kolab.h
 */

#include <config.h>

#include <glib/gi18n-lib.h>

#include "priv-kolab.h"
#include "kolab.h" /* public part of this file */

/*
 * Prototypes for static functions
 */
static void read_event(I_event *ievent, xmlNodePtr node, GError **error);
static gboolean handle_element_show_time_as (I_event *i_event, xmlNodePtr node);
static gboolean handle_element_event(I_event *i_event, xmlNodePtr node, GError **error);


/**
 * Converts a kolab event mail structure to an internal event structure.
 *
 * @param  kevent
 *         a kolab multipart event mail structure
 * @param  error
 *         a glib error structure
 * @return an internal event structure
 *
 * @throws KOLABCONV_ERROR_READ_KOLAB_INPUT_IS_NULL
 *         if the parameter kevent is NULL
 * @throws KOLABCONV_ERROR_READ_KOLAB_MISSING_XML_PART
 *         if the kolab XML mail part could not be found
 * @throws KOLABCONV_ERROR_READ_KOLAB_MALFORMED_XML
 *         if the kolab XML part holds no wellformed XML data
 */
I_event*
conv_kolab_conv_mail_to_I_event (const Kolab_conv_mail *k_event, GError **error)
{
	I_event *ievent = NULL;
	xmlNodePtr node = NULL, n;
	xmlDocPtr doc = NULL;

	log_debug ("\nconv_kolab_conv_mail_to_I_event(): convert Kolab_conv_mail to I_event.");

	if (*error != NULL)
		return NULL;
	/* get parsed kolab XML */
	ievent = new_i_event ();
	doc = util_get_kolab_xml_part(k_event, &ievent->incidence->common->kolab_attachment_store, error);
	if (*error != NULL)
		return NULL;


	/* find root node */
	for (n = doc->children; n != NULL; n = n->next)
		if (n->type == XML_ELEMENT_NODE && g_strcmp0((gchar*)n->name, KLB_EVENT) == 0)
			node = n;

	if (node == NULL) {
		g_set_error (error, KOLABCONV_ERROR_READ_KOLAB,
		             KOLABCONV_ERROR_READ_KOLAB_INVALID_KOLAB_XML,
		             _("Root tag is missing"));
		free_i_event(&ievent);
		xmlFreeDoc(doc);
		return NULL;
	}

	read_event(ievent, node, error);
	xmlFreeDoc(doc);
	if (*error != NULL) {
		free_i_event(&ievent);
		return NULL;
	}

	log_debug ("\nkolabMail to ievent called.");

	return ievent;
}

/**
 * iterate over all child elements of event_node an process them
 */
static void
read_event(I_event *ievent, xmlNodePtr node, GError **error)
{
	xmlNodePtr rec_ptr = NULL; /* pointer used to temporarily store recurrence node */

	xmlNodePtr n_ptr; /* used in for loop */
	for (n_ptr = node->children; n_ptr != NULL; n_ptr = n_ptr->next) {
		if (n_ptr->type == XML_ELEMENT_NODE) {
			gboolean node_processed = FALSE;

			/* save recurrence node in case recurrence has to be
			 * stored in kolabstore due to missing start_date
			 */
			if (strcmp ((gchar*) node->name, KLB_INC_RECURRENCE) == 0)
				rec_ptr = node;

			node_processed = handle_element_event(ievent, n_ptr, error);
			if (*error != NULL)
				return;
			if (!node_processed)
				i_kolab_store_add_xml_element(ievent->incidence->common,
				                              ievent->incidence->common, n_ptr);
		} else
			log_debug("ignored XML node with name %s", n_ptr->name);
	}

	/* cannot be properly converted back from evolution, therefore => kolabstore */
	if (ievent->incidence
	    && ievent->incidence->recurrence
	    && !ievent->incidence->start_date
	    && ievent->incidence->recurrence->recurrence_cycle == I_REC_CYCLE_YEARLY_WEEKDAY) {

		g_free(ievent->incidence->recurrence);
		ievent->incidence->recurrence = NULL;

		i_kolab_store_add_xml_element(ievent->incidence->common, ievent->incidence->common, rec_ptr);
	}

	/* TODO: Validate ievent. (log warnings / create error if necessary) */
}


/**
 * conversion of free/busy information
 */
static gboolean
handle_element_show_time_as (I_event *i_event, xmlNodePtr node)
{
	gchar *value = NULL;

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

	value = xml_get_node_text(node);
	if (g_strcmp0((gchar*) value, KLB_EVENT_SHOW_TIME_AS_FREE) == 0)
		i_event->show_time_as = SHOW_TIME_AS_FREE;
	else if (g_strcmp0((gchar*) value, KLB_EVENT_SHOW_TIME_AS_TENTATIVE) == 0)
		i_event->show_time_as = SHOW_TIME_AS_BUSY; /* SHOW_TIME_AS_TENTATIVE; */
	else if (g_strcmp0((gchar*) value, KLB_EVENT_SHOW_TIME_AS_BUSY) == 0)
		i_event->show_time_as = SHOW_TIME_AS_BUSY;
	else if (g_strcmp0((gchar*) value, KLB_EVENT_SHOW_TIME_AS_OUT_OF_OFFICE) == 0)
		i_event->show_time_as = SHOW_TIME_AS_BUSY; /* SHOW_TIME_AS_OUT_OF_OFFICE; */
	else {
		i_event->show_time_as = SHOW_TIME_AS_BUSY;
		log_warn("illegal show_time_as value '%s' - set to default: Busy", value);
	}
	return TRUE;
}

/**
 * handle event.
 */
static gboolean
handle_element_event(I_event *i_event, xmlNodePtr node, GError **error)
{
	if (conv_incidence_k_to_i(i_event->incidence, node, error))
		return TRUE;
	else if (*error != NULL)
		return FALSE;

	return
		handle_element_show_time_as(i_event, node)
		|| handle_element_date_or_datetime(KLB_EVENT_END_DATE, &i_event->end_date, node);
}
