/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 8; tab-width: 8 -*- */
/*
 * priv-incidence-e-to-i.c
 *
 *  Created on: 29.11.2010
 *      Author: Umer Kayani <u.kayani@tarent.de>,
 *              Hendrik Helwich <h.helwich@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
 */


#include "priv-evolution.h"
#include "evolution-util.h"

/*
 * prototypes for static functions
 */
static Alarm_type alarm_type_e_to_i (ECalComponentAlarmAction action);
static Incidence_status incidence_status_e_to_i (icalparameter_partstat ical_part_type);
static Incidence_cutype incidence_cutype_e_to_i (icalparameter_cutype ical_part_type);
static Incidence_role incidence_role_e_to_i (icalparameter_role ical_role);
static Week_day recurrence_weekday_e_to_i (icalrecurrencetype_weekday weekday);
static Recurrence_cycle recurrence_type_e_to_i (struct icalrecurrencetype *rec_type);
static void recurrence_e_to_i (const ECalComponentWithTZ *ectz, I_incidence *i_incidence);
static void add_recurrence_subfields (I_incidence *i_incidence, struct icalrecurrencetype *rec_type);
static void recurrence_set_by_month_day (struct icalrecurrencetype *rec_type, I_incidence *i_incidence);
static void recurrence_set_by_year_day (struct icalrecurrencetype *rec_type, Recurrence *recurrence);
static void recurrence_set_by_month (struct icalrecurrencetype *rec_type, Recurrence *recurrence);
static void recurrence_set_by_weekday (struct icalrecurrencetype *rec_type, Recurrence *recurrence);
static void recurrence_set_range (struct icalrecurrencetype *rec_type, Recurrence *recurrence);



/**
 * Convert incidence from Evolution to libekolabconv
 */
void
conv_incidence_e_to_i (const ECalComponentWithTZ *ectz, I_incidence *i_incidence)
{
	const gchar *location = NULL;
	ECalComponentText *summary = NULL;
	ECalComponentOrganizer *e_cal_comp_org = NULL;
	ECalComponentDateTime *start_date = NULL;
	GSList *attendee_list = NULL;
	ECalComponentAttendee *ca = NULL;

	conv_common_e_to_i (ectz, i_incidence->common);

	/* ******************************************SET LOCATION************************************ */
	e_cal_component_get_location(ectz->maincomp, &location);
	if (location)
		i_incidence->location = g_string_new(location);

	/* ******************************************SET SUMMARY************************************ */
	summary = g_new0(ECalComponentText, 1);
	e_cal_component_get_summary (ectz->maincomp, summary);
	if (summary && summary->value && *summary->value)
		i_incidence->summary = g_string_new(summary->value);
	else
		i_incidence->summary = NULL;

	g_free(summary);

	/* ******************************************SET ORGANIZER************************************ */
	e_cal_comp_org = g_new0(ECalComponentOrganizer, 1);
	e_cal_component_get_organizer(ectz->maincomp, e_cal_comp_org);
	if (e_cal_comp_org->cn)
		i_incidence->organizer_display_name = g_string_new(e_cal_comp_org->cn);
	if (e_cal_comp_org->value)
		i_incidence->organizer_smtp_address = g_string_new(e_cal_comp_org->value);
	g_free(e_cal_comp_org);


	start_date = g_new0(ECalComponentDateTime, 1);
	e_cal_component_get_dtstart (ectz->maincomp, start_date);
	if (start_date && start_date->value) {
		localtime_to_utc(start_date, ectz->timezone);
		i_incidence->start_date = new_date_or_datetime();
		date_or_datetime_e_to_i(start_date->value, i_incidence->start_date);
	}
	e_cal_component_free_datetime(start_date);
	g_free(start_date);

	/* ******************************************SET ALARM / ADVANCED ALARM ***************************** */

	if (e_cal_component_has_alarms(ectz->maincomp)) {
		/* ECalComponentAlarms *eCalCompAlm = g_new0(ECalComponentAlarms, 1); */
		GList *alarm_list = e_cal_component_get_alarm_uids(ectz->maincomp);

		while (alarm_list) {
			gchar *alarm_uid = ((gchar *)alarm_list->data);
			ECalComponentAlarm *ecalcomp_alarm = e_cal_component_get_alarm(ectz->maincomp, alarm_uid);
			if (ecalcomp_alarm) {
				ECalComponentAlarmTrigger *trigger = NULL;
				ECalComponentAlarmRepeat *repeat = NULL;

				/* new Alarm object to append later at i_incidence list */
				Alarm *alarm = g_new0(Alarm, 1);

				/* type / action */
				ECalComponentAlarmAction action;
				e_cal_component_alarm_get_action (ecalcomp_alarm, &action);
				alarm->type = alarm_type_e_to_i(action);

				if (alarm->type == I_ALARM_TYPE_DISPLAY) {
					ECalComponentText *text = g_new0(ECalComponentText, 1);
					e_cal_component_alarm_get_description(ecalcomp_alarm, text);
					alarm->display_text = g_string_new(text->value);
					g_free(text);
				}
				if (alarm->type == I_ALARM_TYPE_AUDIO) {
					/* set audio-file url */
					icalattach *attach;
					e_cal_component_alarm_get_attach (ecalcomp_alarm, &attach);
					alarm->audio_file = g_string_new(icalattach_get_url(attach));
				}
				if (alarm->type == I_ALARM_TYPE_PROCEDURE) {
					icalattach *attach;
					ECalComponentText *text = NULL;

					alarm = new_alarm(I_ALARM_TYPE_PROCEDURE);

					/* set program */
					e_cal_component_alarm_get_attach (ecalcomp_alarm, &attach);
					alarm->proc_param->program = g_string_new(icalattach_get_url(attach));

					/* set arguments */
					text = g_new0(ECalComponentText, 1);
					e_cal_component_alarm_get_description(ecalcomp_alarm, text);
					alarm->proc_param->arguments = g_string_new(text->value);
					g_free(text);
				}
				if (alarm->type == I_ALARM_TYPE_EMAIL) {
					ECalComponentText *text = NULL;
					GSList *attendee_list = NULL;

					alarm = new_alarm(I_ALARM_TYPE_EMAIL);

					/* set mail text */
					text = g_new0(ECalComponentText, 1);
					e_cal_component_alarm_get_description(ecalcomp_alarm, text);
					alarm->email_param->mail_text = g_string_new(text->value);
					g_free(text);

					/* set mail addresses */
					e_cal_component_alarm_get_attendee_list(ecalcomp_alarm, &attendee_list);
					for (; attendee_list; attendee_list = attendee_list->next) {
						gchar* value = NULL;

						ECalComponentAttendee *ca = (ECalComponentAttendee *) attendee_list->data;

						value = ca->value;
						if (g_str_has_prefix(value, "MAILTO:"))/* increase pointer by 7 to cut off prefix */
							value +=7;

						alarm->email_param->addresses = g_list_append(alarm->email_param->addresses,
						                                              g_string_new(value));
					}

					generic_g_slist_free(&attendee_list, free_attendee);
				}

				/* trigger */
				trigger = g_new0(ECalComponentAlarmTrigger, 1);
				e_cal_component_alarm_get_trigger (ecalcomp_alarm, trigger);
				if (trigger->type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_START)
					alarm->start_offset = (icaldurationtype_as_int(trigger->u.rel_duration)/60); /* (/60) as_int returns seconds, but kolab saved minutes */
				if (trigger->type == E_CAL_COMPONENT_ALARM_TRIGGER_RELATIVE_END)
					alarm->end_offset = (icaldurationtype_as_int(trigger->u.rel_duration)/60); /* (/60) as_int returns seconds, but kolab saved minutes */
				if (trigger->type == E_CAL_COMPONENT_ALARM_TRIGGER_ABSOLUTE) {
					/* TODO: Maybe calculate a relative trigger from incidence->startdate and evolution absolute trigger->u.abs_time -abs_time is icaltimetype, calculate in minutes?
					 *       XXX: Not tested! & Both, Evolution and Kontact do not provide absolute alarm trigger. Just iCal secifies it.
					 *       convert icaltimetype to date_time/time_t for use with time.h
					 */
#if 0
					Date_or_datetime *evo_date_time = NULL;
					time_t *evo_abs_time = NULL;
					i_cal_time_type_to_date_or_datetime(&trigger->u.abs_time, evo_date_time);
					evo_abs_time = evo_date_time->date_time;

					if (incidence->startDate->date_time != NULL) {
						/* calculate difference in seconds with difftime when startDate is already date_time/time_t */
						time_t *i_start_time = incidence->startDate->date_time;
						double diff = 0.0;
						diff = difftime(*evo_abs_time, *i_start_time);	/* returns seconds? */
					}
					else if (incidence->startDate->date != NULL) {
						/* convert startDate from GDate to date_time/time_t and then calculate difference */
						struct tm *stm = NULL;

						/* First convert to a 'struct tm' */
						g_date_to_struct_tm(incidence->startDate->date, stm); 	/* gdate + 0:00:00 */

						/* Then convert to number of seconds */
						time_t *i_start_time = NULL;
						i_start_time = mktime(stm);

						double diff = 0.0;
						diff = difftime(*evo_abs_time, *i_start_time); /* returns seconds? */
					}
#endif
				}
				g_free(trigger);

				/* repeat (count & interval) */
				repeat = g_new0(ECalComponentAlarmRepeat, 1);
				e_cal_component_alarm_get_repeat (ecalcomp_alarm, repeat);
				if (repeat->repetitions)
					alarm->repeat_count = repeat->repetitions;
				if (icaldurationtype_is_null_duration(repeat->duration) == 0)
					alarm->repeat_interval = (icaldurationtype_as_int(repeat->duration)/60); /* (/60) as_int returns seconds, but kolab saved minutes */

				i_incidence->advanced_alarm = g_list_append( i_incidence->advanced_alarm, (Alarm *) alarm);

				g_free(repeat);
			}

			alarm_list = alarm_list->next;
			e_cal_component_alarm_free (ecalcomp_alarm);
		}

		generic_g_list_free(&alarm_list, free_alarm);
	}

	/* ******************************************SET ATTENDEE LIST******************************************************************************* */

	e_cal_component_get_attendee_list(ectz->maincomp, &attendee_list);

	while (attendee_list) {
		Attendee *attendee = g_new0(Attendee, 1);

		ca = (ECalComponentAttendee *) attendee_list->data;

		if (ca->cn)
			attendee->display_name = g_string_new(ca->cn);

		if (g_str_has_prefix(ca->value, "MAILTO:"))
			attendee->smtp_address = g_string_new(ca->value+7); /* increase pointer by 7 to cut off prefix */
		else
			attendee->smtp_address = g_string_new(ca->value);

		attendee->request_response = ca->rsvp;
		/* TODO: Incidence: invitation_sent: get from kolab-store? */
		attendee->role = incidence_role_e_to_i(ca->role);
		attendee->status = incidence_status_e_to_i(ca->status);
		attendee->cutype = incidence_cutype_e_to_i(ca->cutype);

		i_incidence->attendee = g_list_append(i_incidence->attendee, (Attendee *) attendee);

		attendee_list = attendee_list->next;
	}

	generic_g_slist_free(&attendee_list, free_attendee);
	recurrence_e_to_i(ectz, i_incidence);
	i_evo_store_add_cal(i_incidence->common, ectz);

	e_kolab_store_get_fields(ectz, i_incidence->common);
}

/**
 * Convert evolution ECalComponentAlarmAction to libekolabconv Alarm_type
 */
static Alarm_type
alarm_type_e_to_i (ECalComponentAlarmAction action)
{
	switch (action) {
	case E_CAL_COMPONENT_ALARM_AUDIO:
		return I_ALARM_TYPE_AUDIO;
	case E_CAL_COMPONENT_ALARM_DISPLAY:
		return I_ALARM_TYPE_DISPLAY;
	case E_CAL_COMPONENT_ALARM_EMAIL:
		return I_ALARM_TYPE_EMAIL;
	case E_CAL_COMPONENT_ALARM_PROCEDURE:
		return I_ALARM_TYPE_PROCEDURE;
	default:
		return I_ALARM_TYPE_DISPLAY;
	}
}


/**
 * Mapping of incidence status for tasks and events from Evolution side to intern values.
 */
static Incidence_status
incidence_status_e_to_i (icalparameter_partstat ical_part_status)
{
	switch (ical_part_status) {
	case ICAL_PARTSTAT_NEEDSACTION:
		return I_INC_STATUS_NONE;
	case ICAL_PARTSTAT_TENTATIVE:
		return I_INC_STATUS_TENTATIVE;
	case ICAL_PARTSTAT_ACCEPTED:
		return I_INC_STATUS_ACCEPTED;
	case ICAL_PARTSTAT_DECLINED:
		return I_INC_STATUS_DECLINED;
	case ICAL_PARTSTAT_DELEGATED:
		return I_INC_STATUS_DELEGATED;
	default:
		return I_INC_STATUS_NONE;
	}
}

/**
 * Mapping of incidence cutype for tasks and events from Evolution side to intern values.
 */
static Incidence_cutype
incidence_cutype_e_to_i (icalparameter_cutype ical_part_type)
{
	switch (ical_part_type) {
	case ICAL_CUTYPE_INDIVIDUAL:
		return I_INC_CUTYPE_INDIVIDUAL;
	case ICAL_CUTYPE_GROUP:
		return I_INC_CUTYPE_GROUP;
	case ICAL_CUTYPE_RESOURCE:
		return I_INC_CUTYPE_RESOURCE;
	case ICAL_CUTYPE_ROOM:
		return I_INC_CUTYPE_ROOM;
	default:
		return I_INC_CUTYPE_UNDEFINED;
	}
}

/**
 * Maps role for attendees in tasks and events from iCal value to intern value.
 */
static Incidence_role
incidence_role_e_to_i (icalparameter_role ical_role)
{
	switch (ical_role) {
	case ICAL_ROLE_REQPARTICIPANT:
		return I_INC_ROLE_REQUIRED;
	case ICAL_ROLE_OPTPARTICIPANT:
		return I_INC_ROLE_OPTIONAL;
	case ICAL_ROLE_NONPARTICIPANT:
		return I_INC_ROLE_RESOURCE;
	case ICAL_ROLE_CHAIR:
		return I_INC_ROLE_REQUIRED;
	default:
		return I_INC_ROLE_REQUIRED;
	}
}


/**
 * Return the corresponding weekday of enumeration RecurrenceDay to the libical
 * weekday enumeration or zero if the given parameter could not be dedicated to
 * a weekday.
 *
 * @param  weekday
 *         A libical weekday
 * @return A weekday value of RecurrenceDay enumeration or zero if the given
 *         parameter could not be dedicated to a weekday
 */
static Week_day
recurrence_weekday_e_to_i (icalrecurrencetype_weekday weekday)
{
	switch (weekday) {
	case ICAL_NO_WEEKDAY:
		return 0;
	case ICAL_MONDAY_WEEKDAY:
		return I_COMMON_MONDAY;
	case ICAL_TUESDAY_WEEKDAY:
		return I_COMMON_TUESDAY;
	case ICAL_WEDNESDAY_WEEKDAY:
		return I_COMMON_WEDNESDAY;
	case ICAL_THURSDAY_WEEKDAY:
		return I_COMMON_THURSDAY;
	case ICAL_FRIDAY_WEEKDAY:
		return I_COMMON_FRIDAY;
	case ICAL_SATURDAY_WEEKDAY:
		return I_COMMON_SATURDAY;
	case ICAL_SUNDAY_WEEKDAY:
		return I_COMMON_SUNDAY;
	default:
		log_warn("invalid weekday enumeration value: %d", weekday);
		return 0;
	}
}


/**
 * Convert the iCal recurrence type to the internal recurrence cycle enumeration
 */
static Recurrence_cycle
recurrence_type_e_to_i (struct icalrecurrencetype *rec_type)
{
	if (rec_type->freq == ICAL_DAILY_RECURRENCE)
		return I_REC_CYCLE_DAILY;
	else if (rec_type->freq == ICAL_WEEKLY_RECURRENCE)
		return I_REC_CYCLE_WEEKLY;
	else if (rec_type->freq == ICAL_MONTHLY_RECURRENCE) {
		if (rec_type->by_day[0] != ICAL_RECURRENCE_ARRAY_MAX)
			return I_REC_CYCLE_MONTHLY_WEEKDAY;
		else
			return I_REC_CYCLE_MONTHLY_DAYNUMBER;
	}
	else if (rec_type->freq == ICAL_YEARLY_RECURRENCE && *rec_type->by_day != ICAL_RECURRENCE_ARRAY_MAX)
		return I_REC_CYCLE_YEARLY_WEEKDAY;
	else if (rec_type->freq == ICAL_YEARLY_RECURRENCE && *rec_type->by_year_day != ICAL_RECURRENCE_ARRAY_MAX)
		return I_REC_CYCLE_YEARLY_YEARDAY;
	else
		return I_REC_CYCLE_YEARLY_MONTHDAY;
}

/**
 * Convert the evolution recurrence to the internal recurrence structure
 */
static void
recurrence_e_to_i (const ECalComponentWithTZ *ectz, I_incidence *i_incidence)
{
	GSList *exdate_list = NULL;
	GSList *rec_list = NULL;

	/* ******************************************SET RECURRENCE******************************************************************************* */
	/* ******************************************SET RECURRENCE EXCLUSIONS******************************************************************** */
	e_cal_component_get_exdate_list (ectz->maincomp, &exdate_list);
	if (exdate_list)
		i_incidence->recurrence = new_recurrence();

	while (exdate_list) {
		ECalComponentDateTime *e_cal_date_time = (ECalComponentDateTime *) exdate_list->data;

		GDate *exclusion_date = g_date_new_dmy((GDateDay) e_cal_date_time->value->day,
		                                       (GDateMonth) e_cal_date_time->value->month,
		                                       (GDateYear)e_cal_date_time->value->year);
		i_incidence->recurrence->exclusion = g_list_append( i_incidence->recurrence->exclusion, (GDate *) exclusion_date);

		exdate_list = exdate_list->next;
	}
	g_slist_free(exdate_list);
	/* ******************************************SET RECURRENCE CYCLE******************************************************************** */
	e_cal_component_get_rrule_list (ectz->maincomp, &rec_list);

	while (rec_list != NULL) {
		struct icalrecurrencetype *rec_type = (struct icalrecurrencetype *) rec_list->data;

		if (i_incidence->recurrence == NULL)
			i_incidence->recurrence = new_recurrence();

		i_incidence->recurrence->recurrence_cycle = recurrence_type_e_to_i (rec_type);
		recurrence_set_range (rec_type, i_incidence->recurrence);
		i_incidence->recurrence->interval = rec_type->interval;

		add_recurrence_subfields (i_incidence, rec_type);

		/* remapping of missing I_REC_CYCLE_YEARLY_WEEKDAY support in evolution */
		if (rec_type->freq == ICAL_MONTHLY_RECURRENCE
		    && rec_type->by_day[0] != ICAL_RECURRENCE_ARRAY_MAX
		    && rec_type->by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX
		    && rec_type->by_set_pos[1] == ICAL_RECURRENCE_ARRAY_MAX
		    && i_incidence->recurrence->interval == 12) {
			gint month = 0;

			i_incidence->recurrence->recurrence_cycle = I_REC_CYCLE_YEARLY_WEEKDAY;
			i_incidence->recurrence->interval = 1;

			if (i_incidence->start_date && i_incidence->start_date->date)
				month = g_date_get_month(i_incidence->start_date->date);
			else if (i_incidence->start_date && i_incidence->start_date->date_time != NULL) {
				struct tm *ts = gmtime(i_incidence->start_date->date_time);
				month = ts->tm_mon + 1;
			}
			i_incidence->recurrence->month = month;
		}

		if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_YEARLY_MONTHDAY && i_incidence->start_date) {
			if (i_incidence->start_date->date) {
				i_incidence->recurrence->month = g_date_get_month(i_incidence->start_date->date);
				i_incidence->recurrence->day_number = g_date_get_day(i_incidence->start_date->date);
			} else if (i_incidence->start_date->date_time) {
				struct tm *ts = gmtime(i_incidence->start_date->date_time);
				i_incidence->recurrence->month = ts->tm_mon + 1;
				i_incidence->recurrence->day_number = ts->tm_mday;
			}
#if 0
			icalcomponent *icomp = e_cal_component_get_icalcomponent(ectz->maincomp);
			icalcomponent_kind ical_kind = icalcomponent_isa(icomp);
			if (ical_kind == ICAL_VTODO_COMPONENT) {
				ECalComponentDateTime *dt;
				e_cal_component_get_due(ectz->maincomp, dt);
				if (dt) {
					i_incidence->recurrence->month = dt->value->month;
					i_incidence->recurrence->day_number = dt->value->day;
				}
			}
#endif
		}

		g_free(rec_type);
		rec_list = rec_list->next;
	}
	g_slist_free(rec_list);
}

/**
 * Convert the iCal recurrence type subfields to the internal recurrence
 * structure
 */
static void
add_recurrence_subfields (I_incidence *i_incidence, struct icalrecurrencetype *rec_type)
{
	if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_DAILY) {
		recurrence_set_by_weekday(rec_type, i_incidence->recurrence);
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_WEEKLY) {
		recurrence_set_by_weekday(rec_type, i_incidence->recurrence);
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_MONTHLY_DAYNUMBER) {
		recurrence_set_by_month_day(rec_type, i_incidence);
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_MONTHLY_WEEKDAY) {
		if (rec_type->by_set_pos[0] != ICAL_RECURRENCE_ARRAY_MAX)
			i_incidence->recurrence->day_number = rec_type->by_set_pos[0];
		recurrence_set_by_weekday(rec_type, i_incidence->recurrence);
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_YEARLY_MONTHDAY) {
		/* disabled, cannot be properly handled by Evolution */
#if 0
		recurrence_set_by_month_day(rec_type, i_incidence);
		recurrence_set_by_month(rec_type, i_incidence->recurrence);
#endif
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_YEARLY_YEARDAY) {
		recurrence_set_by_year_day(rec_type, i_incidence->recurrence);
	} else if (i_incidence->recurrence->recurrence_cycle == I_REC_CYCLE_YEARLY_WEEKDAY) {
		recurrence_set_by_month_day(rec_type, i_incidence);
		recurrence_set_by_weekday(rec_type, i_incidence->recurrence);
		recurrence_set_by_month(rec_type, i_incidence->recurrence);
	} else {
		log_debug("\nError: Unknown recurrence Cycle.");
	}
}


/**
 * Convert the iCal recurrence type to the internal recurrence structure
 */
static void
recurrence_set_by_month_day (struct icalrecurrencetype *rec_type, I_incidence *i_incidence)
{
	if (rec_type->by_month_day[0] != ICAL_RECURRENCE_ARRAY_MAX)
		i_incidence->recurrence->day_number = rec_type->by_month_day[0];
	else if (i_incidence->start_date && i_incidence->start_date->date_time) {
		struct tm *tt = gmtime(i_incidence->start_date->date_time);
		i_incidence->recurrence->day_number = tt->tm_mday;
		i_incidence->recurrence->month = tt->tm_mon+1;
	}
}

/**
 * Convert the iCal recurrence type to the internal recurrence structure
 */
static void
recurrence_set_by_year_day (struct icalrecurrencetype *rec_type, Recurrence *recurrence)
{
	if (rec_type->by_year_day[0] != ICAL_RECURRENCE_ARRAY_MAX)
		recurrence->day_number = rec_type->by_year_day[0];
}

/**
 * Convert the iCal recurrence type to the internal recurrence structure
 */
static void
recurrence_set_by_month (struct icalrecurrencetype *rec_type, Recurrence *recurrence)
{
	if (rec_type->by_month[0] !=  ICAL_RECURRENCE_ARRAY_MAX)
		recurrence->month = rec_type->by_month[0];
}

/**
 * Convert the iCal recurrence type to the internal recurrence structure
 */
static void
recurrence_set_by_weekday (struct icalrecurrencetype *rec_type, Recurrence *recurrence)
{
	gint i;
	for (i = 0; rec_type->by_day[i] != ICAL_RECURRENCE_ARRAY_MAX; i++)
		recurrence->weekdays |= (gint) recurrence_weekday_e_to_i (rec_type->by_day[i]);
}


/**
 * Convert the iCal recurrence type to the internal recurrence structure
 */
static void
recurrence_set_range(struct icalrecurrencetype *rec_type, Recurrence *recurrence)
{
	if (icaltime_is_date (rec_type->until) == TRUE) {
		recurrence->range_date = g_date_new_dmy((GDateDay) rec_type->until.day,
		                                        (GDateMonth) rec_type->until.month,
		                                        (GDateYear) rec_type->until.year);
	} else if (rec_type->count > 0) {
		recurrence->range_number = g_new0(gint, 1);
		*recurrence->range_number = rec_type->count;
	} else {
		/* infinite recurrence */
	}
}
