/*
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
 * Copyright (C) 1999-2004 Hiroyuki Yamamoto & the Sylpheed-Claws team
 * This file (C) 2004 Colin Leroy <colin@colino.net>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 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 General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#ifdef HAVE_CONFIG_H
#  include "config.h"
#  include "pluginconfig.h"
#endif

#include <ical.h>
#include "gettext.h"
#include <gtk/gtk.h>

#include "mimeview.h"
#include "utils.h"
#include "vcalendar.h"
#include "vcal_manager.h"
#include "vcal_folder.h"
#include "vcal_meeting_gtk.h"
#include "prefs_account.h"
#include "prefs_common.h"
#include "account.h"
#include "codeconv.h"
#include "xml.h"
#include "xmlprops.h"
#include "alertpanel.h"
#include "vcal_prefs.h"

MimeViewerFactory vcal_viewer_factory;

static void refresh_folder_contents(VCalViewer *vcalviewer);
static GdkColor uri_color = {
	(gulong)0,
	(gushort)0,
	(gushort)0,
	(gushort)0
};

struct _VCalViewer
{
	MimeViewer mimeviewer;

	gchar	  *file;
	MimeInfo  *mimeinfo;
	gchar 	  *tmpfile;
	icalcomponent *comp;
	icalcomponent *icomp;
	
	GtkWidget *scrolledwin;
	GtkWidget *table;
	GtkWidget *type;
	GtkWidget *who;
	GtkWidget *start;
	GtkWidget *end;
	GtkWidget *summary;
	GtkWidget *description;
	gchar	  *url;
	GtkWidget *answer;
	GtkWidget *button;
	GtkWidget *reedit;
	GtkWidget *cancel;
	GtkWidget *uribtn;
	GtkWidget *attendees;
};

static gchar *get_tmpfile(VCalViewer *vcalviewer)
{
	gchar *tmpfile = NULL;
	
	if (!vcalviewer->tmpfile) {
		tmpfile = procmime_get_tmp_file_name(vcalviewer->mimeinfo);
		debug_print("creating %s\n", tmpfile);

		if (procmime_get_part(tmpfile, vcalviewer->mimeinfo) < 0) {
			g_warning("Can't get mimepart file");	
			g_free(tmpfile);
			return NULL;
		}
		vcalviewer->tmpfile = tmpfile;
	}
	
	return vcalviewer->tmpfile;
}

static GtkWidget *vcal_viewer_get_widget(MimeViewer *_mimeviewer)
{
	VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;

	debug_print("vcal_viewer_get_widget\n");
	gtk_widget_show_all(vcalviewer->scrolledwin);
	return vcalviewer->scrolledwin;
}

static void vcal_viewer_clear_viewer(MimeViewer *_mimeviewer)
{
	VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;

	debug_print("vcal_viewer_clear_viewer\n");

	g_free(vcalviewer->file);
	vcalviewer->file = NULL;
	if (vcalviewer->tmpfile) {
		debug_print("unlinking %s\n", vcalviewer->tmpfile);
		unlink(vcalviewer->tmpfile);
		g_free(vcalviewer->tmpfile);
		vcalviewer->tmpfile = NULL;
	}
	vcalviewer->mimeinfo = NULL;
}

static gchar *get_email_from_attendee_property(icalproperty *p)
{
	gchar *tmp = NULL;
	gchar *email = NULL;
	
	if (p)
		tmp = g_strdup(icalproperty_get_attendee(p));

	if (!tmp) 
		return NULL;
		
	if (!strncasecmp(tmp, "MAILTO:", strlen("MAILTO:")))
		email = g_strdup(tmp+strlen("MAILTO:"));
	else
		email = g_strdup(tmp);
	g_free(tmp);
	
	return email;
}

static gchar *get_name_from_organizer_property(icalproperty *p)
{
	gchar *tmp = NULL;
	
	if (p && icalproperty_get_parameter_as_string(p, "CN") != NULL)
		tmp = g_strdup(icalproperty_get_parameter_as_string(p, "CN"));

	return tmp;
}

static gchar *get_email_from_organizer_property(icalproperty *p)
{
	gchar *tmp = NULL;
	gchar *email = NULL;
	
	if (p)
		tmp = g_strdup(icalproperty_get_organizer(p));

	if (!tmp) 
		return NULL;

	if (!strncasecmp(tmp, "MAILTO:", strlen("MAILTO:")))
		email = g_strdup(tmp+strlen("MAILTO:"));
	else
		email = g_strdup(tmp);
	g_free(tmp);
	
	return email;
}

static icalproperty *vcalviewer_get_property(VCalViewer *vcalviewer, icalproperty_kind kind)
{
	icalproperty *iprop = NULL;
	
	if (!vcalviewer->icomp || !vcalviewer->comp)
		return NULL;

	iprop = icalcomponent_get_first_property(vcalviewer->icomp, kind);
	if (!iprop)
		iprop = icalcomponent_get_first_property(vcalviewer->comp, kind);
	
	return iprop;
}

static GSList *vcalviewer_get_properties(VCalViewer *vcalviewer, icalproperty_kind kind)
{
	GSList *list = NULL;
	icalproperty *iprop = NULL;
	
	if (!vcalviewer->icomp || !vcalviewer->comp)
		return NULL;

	iprop = icalcomponent_get_first_property(vcalviewer->icomp, kind);
	if (!iprop) {
		return NULL;
	} else do {
		list = g_slist_append(list, iprop);
	} while ((iprop = icalcomponent_get_next_property(vcalviewer->icomp, kind)) != NULL);
	
	return list;
}

static icalcomponent *vcalviewer_get_component(const gchar *file)
{
	gchar *compstr = NULL;
	icalcomponent *comp = NULL;
	FILE *fp;
	GByteArray *array;
	gchar buf[BUFSIZ];
	gint n_read;
	gchar *str;

	g_return_val_if_fail(file != NULL, NULL);

	if ((fp = fopen(file, "rb")) == NULL) {
		FILE_OP_ERROR(file, "fopen");
		return NULL;
	}

	array = g_byte_array_new();

	while ((n_read = fread(buf, sizeof(gchar), sizeof(buf), fp)) > 0) {
		if (n_read < sizeof(buf) && ferror(fp))
			break;
		g_byte_array_append(array, buf, n_read);
	}

	if (ferror(fp)) {
		FILE_OP_ERROR("file stream", "fread");
		g_byte_array_free(array, TRUE);
		return NULL;
	}

	buf[0] = '\0';
	g_byte_array_append(array, buf, 1);
	compstr = (gchar *)array->data;
	g_byte_array_free(array, FALSE);

	fclose(fp);	

	if (compstr) {
		comp = icalcomponent_new_from_string(compstr);
		g_free(compstr);
	}
	
	return comp;
}

#define GTK_LABEL_SET_TEXT_TRIMMED(label, text) {		\
	gchar *tmplbl = strretchomp(g_strdup(text));		\
	gtk_label_set_text(label, tmplbl);			\
	g_free(tmplbl);						\
}

static void vcalviewer_reset(VCalViewer *vcalviewer) 
{
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
	g_free(vcalviewer->url);
	vcalviewer->url = NULL;
	gtk_widget_hide(vcalviewer->uribtn);
}

static gchar *get_attendee_replying(VCalViewer *vcalviewer)
{
	gchar *attendee = NULL;
	icalproperty *p = NULL;
	
	p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	if (!p)
		return NULL;

	attendee = get_email_from_attendee_property(p);

	icalproperty_free(p);
	
	return attendee;
	
}

static gchar *get_attendee_replying_name(VCalViewer *vcalviewer)
{
	gchar *name = NULL;
	icalproperty *p = NULL;
	icalparameter *param = NULL;
	
	p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	if (!p)
		return NULL;

	param = icalproperty_get_first_parameter(p, ICAL_CN_PARAMETER);
	if (param)
		name = g_strdup(icalparameter_get_cn(param));
		
	icalproperty_free(p);
	
	return name;
	
}

enum icalparameter_partstat get_attendee_reply(VCalViewer *vcalviewer)
{
	icalproperty *p = NULL;
	icalparameter *param = NULL;
	enum icalparameter_partstat status = 0;
	
	p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	if (!p)
		return 0;
	
	param = icalproperty_get_first_parameter(p, ICAL_PARTSTAT_PARAMETER);
	
	if (param) {
		status = icalparameter_get_partstat(param);
		icalproperty_free(p);
	}
	
	return status;
}

enum icalparameter_partstat get_attendee_replying_cutype(VCalViewer *vcalviewer)
{
	icalproperty *p = NULL;
	icalparameter *param = NULL;
	enum icalparameter_cutype status = 0;
	
	p = vcalviewer_get_property(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	if (!p)
		return 0;
	
	param = icalproperty_get_first_parameter(p, ICAL_CUTYPE_PARAMETER);
	
	if (param) {
		status = icalparameter_get_cutype(param);
		icalproperty_free(p);
	}
	
	return status;
}

/*FIXME*/
static void vcalviewer_get_attendees(VCalViewer *vcalviewer, VCalEvent *event)
{
	GSList *attendees = vcalviewer_get_properties(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	GSList *cur = attendees;
	while (cur && cur->data) {
		icalproperty *iprop = (icalproperty *)cur->data;
		gchar *email = get_email_from_attendee_property(iprop);
		const gchar *name  = NULL;
		icalparameter *param = NULL;
		icalparameter *cutype = NULL;
		param = icalproperty_get_first_parameter(iprop, ICAL_CN_PARAMETER);
		if (param)
			name = icalparameter_get_cn(param);
		
		param = icalproperty_get_first_parameter(iprop, ICAL_PARTSTAT_PARAMETER);
		cutype= icalproperty_get_first_parameter(iprop, ICAL_CUTYPE_PARAMETER);
		
		if (email && param) {
			debug_print("updating %s: %d\n", email, icalparameter_get_partstat(param));
			vcal_manager_update_answer(event, email, name,
				icalparameter_get_partstat(param),
				cutype?icalparameter_get_cutype(cutype):ICAL_CUTYPE_INDIVIDUAL);
		} else if (email) {
			debug_print("updating %s: %d\n", email, ICAL_PARTSTAT_NEEDSACTION);
			vcal_manager_update_answer(event, email, name,
				ICAL_PARTSTAT_NEEDSACTION,
				cutype?icalparameter_get_cutype(cutype):ICAL_CUTYPE_INDIVIDUAL);
		}
		g_free(email);
		icalproperty_free(iprop);
		
		cur = cur->next;
	}
	g_slist_free(cur);
}


static PrefsAccount *get_account_from_attendee(icalproperty *attendee)
{
	gchar *email = get_email_from_attendee_property(attendee);
	if (email != NULL && account_find_from_address(email) != NULL)
		return account_find_from_address(email);

	return NULL;
}

static PrefsAccount *get_account_from_attendees(VCalViewer *vcalviewer)
{
	GSList *attendees = vcalviewer_get_properties(vcalviewer, ICAL_ATTENDEE_PROPERTY);
	GSList *cur = attendees;
	PrefsAccount *account = NULL;
	while (cur && cur->data) {
		icalproperty *iprop = (icalproperty *)cur->data;
		
		if (get_account_from_attendee(iprop)) {
			account = get_account_from_attendee(iprop);
			icalproperty_free(iprop);
			break;
		}

		icalproperty_free(iprop);
		cur = cur->next;
	}
	g_slist_free(cur);
	return account;
}

static void vcalviewer_answer_set_choices(VCalViewer *vcalviewer, VCalEvent *event, enum icalproperty_method method)
{
	int i = 0;
	
	gtk_widget_hide(vcalviewer->reedit);
	gtk_widget_hide(vcalviewer->cancel);
	gtk_widget_hide(vcalviewer->answer);
	gtk_widget_hide(vcalviewer->button);

	for (i = 0; i < 3; i++) 
		gtk_combo_box_remove_text(GTK_COMBO_BOX(vcalviewer->answer), 0);
	
	if (method == ICAL_METHOD_REQUEST) {
		gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Accept"));
		gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Tentatively accept"));
		gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), _("Decline"));
		gtk_widget_set_sensitive(vcalviewer->answer, TRUE);
		gtk_widget_set_sensitive(vcalviewer->button, TRUE);
		gtk_widget_show(vcalviewer->answer);
		gtk_widget_show(vcalviewer->button);
	} else {
		gtk_combo_box_append_text(GTK_COMBO_BOX(vcalviewer->answer), "-");
		gtk_widget_set_sensitive(vcalviewer->answer, FALSE);
		gtk_widget_set_sensitive(vcalviewer->button, FALSE);
	}
	gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
	
	if (event && event->method == ICAL_METHOD_REQUEST) {
		PrefsAccount *account = vcal_manager_get_account_from_event(event);
		if (account) {
			enum icalparameter_partstat answer = 
				vcal_manager_get_reply_for_attendee(event, account->address);
				
			if (answer == ICAL_PARTSTAT_ACCEPTED)
				gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 0);
			if (answer == ICAL_PARTSTAT_TENTATIVE)
				gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 1);
			if (answer == ICAL_PARTSTAT_DECLINED)
				gtk_combo_box_set_active(GTK_COMBO_BOX(vcalviewer->answer), 2);
		}
	}
}

void vcalviewer_display_event (VCalViewer *vcalviewer, VCalEvent *event)
{
	GSList *list = NULL;
	gchar *attendees = NULL;
	gboolean firstatt = TRUE;
	gboolean mine = FALSE;
	gchar *label = NULL;
	
	if (!event)
		return;
	if (!vcalviewer)
		return;

	if (event->type == ICAL_VTODO_COMPONENT) {
		label = g_strjoin(" ", _("You have a Todo item."),
				_("Details follow:"), NULL);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
	} else if (event->method == ICAL_METHOD_REQUEST) {
		if (account_find_from_address(event->organizer)) {
			label = g_strjoin(" ", _("You have created a meeting."),
					_("Details follow:"), NULL);
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
			mine = TRUE;
		} else {
			label = g_strjoin(" ", _("You have been invited to a meeting."),
						_("Details follow:"), NULL);
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
		}
	}
	else if (event->method == ICAL_METHOD_REPLY) {
		enum icalparameter_partstat answer = get_attendee_reply(vcalviewer);
		enum icalparameter_cutype cutype = get_attendee_replying_cutype(vcalviewer);
		gchar *attendee = get_attendee_replying(vcalviewer);
		gchar *name = get_attendee_replying_name(vcalviewer);
		
		vcal_manager_update_answer(event, attendee, name, answer, cutype);

		if (!attendee) {
			label = g_strjoin(" ",
				_("You have received an answer to an unknown meeting proposal."),
				_("Details follow:"), NULL);
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
		} else {
			label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
				"%s has %s the invitation whose details follow:"),
				attendee, vcal_manager_get_reply_text_for_attendee(event, attendee));
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
			g_free(attendee);
		}
	} else if (event->method == ICAL_METHOD_CANCEL) {
		label = g_strjoin(" ",
				_("A meeting to which you had been invited has been cancelled."),
				_("Details follow:"), NULL);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
		vcal_manager_save_event(event);
		refresh_folder_contents(vcalviewer);
	} else {
		label = g_strjoin(" ", _("You have been forwarded an appointment."),
				_("Details follow:"), NULL);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
	}
	g_free(label);

	if (event->orgname && strlen(event->orgname)
	&&  event->organizer && strlen(event->organizer)) {
		gchar *addr = g_strconcat(event->orgname, " <", event->organizer, ">", NULL);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
		g_free(addr);
	} else if (event->organizer && strlen(event->organizer)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), event->organizer);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
	}
	if (event->summary && strlen(event->summary)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), event->summary);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
	}
	if (event->description && strlen(event->description)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), event->description);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
	}
	g_free(vcalviewer->url);
	if (event->url && strlen(event->url)) {
		vcalviewer->url = g_strdup(event->url);
		gtk_widget_show(vcalviewer->uribtn);
	} else {
		vcalviewer->url = NULL;
		gtk_widget_hide(vcalviewer->uribtn);
	}
	
	if (event->start && strlen(event->start)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), event->start);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
	}
	if (event->end && strlen(event->end)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), event->end);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
	}
	for (list = vcal_manager_get_answers_emails(event); 
	     list && list->data; list = list->next) {
	     	gchar *attendee = (gchar *)list->data;
		gchar *name = vcal_manager_get_attendee_name(event, attendee);
		gchar *answer = vcal_manager_get_reply_text_for_attendee(event, attendee);
		gchar *type = vcal_manager_get_cutype_text_for_attendee(event, attendee);
		if (firstatt) {
			attendees = g_strdup_printf("%s%s<%s> (%s, %s)", 
					(name && strlen(name))?name:"",
					(name && strlen(name))?" ":"",
					attendee, type, answer);
			firstatt = FALSE;
		} else {
			gchar *tmp = g_strdup(attendees);
			g_free(attendees);
			attendees = g_strdup_printf("%s\n%s%s<%s> (%s, %s)", 
					tmp, (name && strlen(name))?name:"",
					(name && strlen(name))?" ":"", 
					attendee, type, answer);
			g_free(tmp);
		}
		g_free(answer);
		g_free(type);
		g_free(name);
	}

	if (attendees && strlen(attendees)) {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), attendees);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-");
	}
	if (!mine)
		if (event->type != ICAL_VTODO_COMPONENT)
			vcalviewer_answer_set_choices(vcalviewer, event, event->method);
		else
			vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_PUBLISH);
	else {
		vcalviewer_answer_set_choices(vcalviewer, event, ICAL_METHOD_REPLY);
		gtk_widget_show(vcalviewer->reedit);
		gtk_widget_show(vcalviewer->cancel);
	}
}

gchar *vcalviewer_get_uid_from_mimeinfo(MimeInfo *mimeinfo)
{
	gchar *tmpfile = procmime_get_tmp_file_name(mimeinfo);
	gchar *compstr = NULL;
	icalcomponent *comp = NULL, *icomp = NULL;
	icalproperty *iprop = NULL;
	gchar *res = NULL;

	if (procmime_get_part(tmpfile, mimeinfo) < 0) {
		g_warning("Can't get mimepart file");	
		g_free(tmpfile);
		return NULL;
	}
	
	compstr = file_read_to_str(tmpfile);
	unlink(tmpfile);
	g_free(tmpfile);
	comp = icalcomponent_new_from_string(compstr);
	g_free(compstr);
	if (!comp) {
		g_warning("can't get component");
		return NULL;
	}
	icomp = icalcomponent_get_inner(comp);
	if (!icomp) {
		g_warning("can't get inner component");
		icalcomponent_free(comp);
		return NULL;
	}
	iprop = icalcomponent_get_first_property(icomp, ICAL_UID_PROPERTY);

	if (iprop) {
		res = g_strdup(icalproperty_get_uid(iprop));
		icalproperty_free(iprop);
	} else {
		g_warning("can't get property");
	}

	icalcomponent_free(comp);
	
	debug_print("got uid: %s\n", res);
	return res;

}

static void vcalviewer_get_request_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo, gboolean is_todo) 
{
	icalproperty *iprop = NULL;
	gchar *org = NULL, *summary = NULL, *description = NULL, *url = NULL;
	gchar *dtstart = NULL, *dtend = NULL, *tzid = NULL, *orgname = NULL;
	enum icalproperty_method method = ICAL_METHOD_REQUEST;
	VCalEvent *event = NULL;
	gchar *tmp;
	const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
	const gchar *saveme =  procmime_mimeinfo_get_parameter(mimeinfo, "vcalsave");
	gchar * uid = vcalviewer_get_uid_from_mimeinfo(mimeinfo);
	gint sequence = 0;
	
	if (!charset)
		charset=CS_ISO_8859_1;
		
	iprop = vcalviewer_get_property(vcalviewer, ICAL_SEQUENCE_PROPERTY);
	if (iprop) {
		sequence = icalproperty_get_sequence(iprop);
		icalproperty_free(iprop);
	}  

	iprop = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
	if (iprop) {
		method = icalproperty_get_method(iprop);
		icalproperty_free(iprop);
	}
	
	/* see if we have it registered and more recent */
	event = vcal_manager_load_event(uid);
	if (event && event->sequence >= sequence) {
		charset = CS_INTERNAL;
		event->method = method;
		vcalviewer_display_event(vcalviewer, event);
		vcal_manager_free_event(event);
		g_free(uid);
		return;
	} else if (event) {
		vcal_manager_free_event(event);
	}

	/* load it and register it */

	iprop = vcalviewer_get_property(vcalviewer, ICAL_ORGANIZER_PROPERTY);
	if (iprop) {
		tmp = get_email_from_organizer_property(iprop);
		if (tmp && !g_utf8_validate(tmp, -1, NULL))
			org = conv_codeset_strdup(tmp, charset, CS_UTF_8);
		else if (tmp)
			org = g_strdup(tmp);
		else
			org = NULL;
		g_free(tmp);
		icalproperty_free(iprop);
		tmp = get_name_from_organizer_property(iprop);
		if (tmp && !g_utf8_validate(tmp, -1, NULL))
			orgname = conv_codeset_strdup(tmp, charset, CS_UTF_8);
		else if (tmp)
			orgname = g_strdup(tmp);
		else
			orgname = NULL;
		g_free(tmp);
	} 
	
	iprop = vcalviewer_get_property(vcalviewer, ICAL_SUMMARY_PROPERTY);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_summary(iprop), -1, NULL))
			summary = conv_codeset_strdup(icalproperty_get_summary(iprop), charset, CS_UTF_8);
		else
			summary = g_strdup(icalproperty_get_summary(iprop));
		icalproperty_free(iprop);
	} 

	iprop = vcalviewer_get_property(vcalviewer, ICAL_DESCRIPTION_PROPERTY);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_description(iprop), -1, NULL))
			description = conv_codeset_strdup(icalproperty_get_description(iprop), charset, CS_UTF_8);
		else
			description = g_strdup(icalproperty_get_description(iprop));
		icalproperty_free(iprop);
	} 
	
	iprop = vcalviewer_get_property(vcalviewer, ICAL_URL_PROPERTY);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_url(iprop), -1, NULL))
			url = conv_codeset_strdup(icalproperty_get_url(iprop), charset, CS_UTF_8);
		else
			url = g_strdup(icalproperty_get_url(iprop));
		icalproperty_free(iprop);
	} 
	
	iprop = vcalviewer_get_property(vcalviewer, ICAL_DTSTART_PROPERTY);
	if (iprop) {
		struct icaltimetype itt = icalproperty_get_dtstart(iprop);
		dtstart = g_strdup(icaltime_as_ical_string(itt));
		icalproperty_free(iprop);
	} 

	iprop = vcalviewer_get_property(vcalviewer, ICAL_DTEND_PROPERTY);
	if (iprop) {
		struct icaltimetype itt = icalproperty_get_dtend(iprop);
		dtend = g_strdup(icaltime_as_ical_string(itt));
		icalproperty_free(iprop);
	} 
	
	iprop = vcalviewer_get_property(vcalviewer, ICAL_TZID_PROPERTY);
	if (iprop) {
		tzid = g_strdup(icalproperty_get_tzid(iprop));
		icalproperty_free(iprop);
	} 
	
	iprop = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
	if (iprop) {
		method = icalproperty_get_method(iprop);
		icalproperty_free(iprop);
	}
	
	event = vcal_manager_new_event( uid,
					org, orgname, summary, description, 
					dtstart, dtend, tzid, url, method, sequence, 
					is_todo?ICAL_VTODO_COMPONENT:ICAL_VEVENT_COMPONENT);
	vcalviewer_get_attendees(vcalviewer, event);
	if (!saveme || strcmp(saveme,"no"))
		vcal_manager_save_event(event);

	g_free(org); 
	g_free(orgname); 
	g_free(summary);
	g_free(description);
	g_free(url);
	g_free(uid);
	vcalviewer_display_event(vcalviewer, event);
	vcal_manager_free_event(event);
}

static void vcalviewer_get_reply_values(VCalViewer *vcalviewer, MimeInfo *mimeinfo) 
{
	icalproperty *iprop = NULL;
	gchar *tmp = NULL;
	const gchar *charset = procmime_mimeinfo_get_parameter(mimeinfo, "charset");
	gchar *label = NULL;
	enum icalparameter_partstat answer = get_attendee_reply(vcalviewer);
	enum icalparameter_cutype cutype = get_attendee_replying_cutype(vcalviewer);
	gchar *attendee = get_attendee_replying(vcalviewer);
	gchar *name = get_attendee_replying_name(vcalviewer);

	if (!charset)
		charset=CS_ISO_8859_1;

	iprop = vcalviewer_get_property(vcalviewer, ICAL_UID_PROPERTY);
	if (iprop) {
		VCalEvent *event = vcal_manager_load_event(icalproperty_get_uid(iprop));
		if (event) {
			charset = CS_INTERNAL;
			event->method = ICAL_METHOD_REPLY;
			vcalviewer_display_event(vcalviewer, event);
			vcal_manager_free_event(event);
			return;
		} 
	} 
	
	/* unknown answer but get the replier anyway */
		
	if (!attendee) {
		label = g_strjoin(" ",
			_("You have received an answer to an unknown meeting proposal."),
			_("Details follow:"), NULL);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
	} else {
		label = g_strdup_printf(_("You have received an answer to a meeting proposal.\n"
			"%s has %s the invitation whose details follow:"),
			attendee, vcal_manager_answer_get_text(answer));
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->type), label);
		g_free(attendee);
	}

	g_free(label);

	iprop = vcalviewer_get_property(vcalviewer, ICAL_ORGANIZER_PROPERTY);
	if (iprop) {
		gchar *org, *orgname;
		tmp = get_email_from_organizer_property(iprop);
		if (tmp && !g_utf8_validate(tmp, -1, NULL))
			org = conv_codeset_strdup(tmp, charset, CS_UTF_8);
		else if (tmp)
			org = g_strdup(tmp);
		else
			org = NULL;
		g_free(tmp);
		tmp = get_name_from_organizer_property(iprop);
		if (tmp && !g_utf8_validate(tmp, -1, NULL))
			orgname = conv_codeset_strdup(tmp, charset, CS_UTF_8);
		else if (tmp)
			orgname = g_strdup(tmp);
		else
			orgname = NULL;
		g_free(tmp);
		if (orgname && org) {
			gchar *addr = g_strconcat(orgname, " <", org, ">", NULL);
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), addr);
			g_free(addr);
		} else if (org) {
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), org);
		} else {
			GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
		}
		icalproperty_free(iprop);
		g_free(org);
		g_free(orgname);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->who), "-");
	}
	iprop = vcalviewer_get_property(vcalviewer, ICAL_SUMMARY_PROPERTY);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_summary(iprop), -1, NULL))
			tmp = conv_codeset_strdup(icalproperty_get_summary(iprop), charset, CS_UTF_8);
		else
			tmp = g_strdup(icalproperty_get_summary(iprop));
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), tmp);
		g_free(tmp);
		icalproperty_free(iprop);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->summary), "-");
	}
	iprop = vcalviewer_get_property(vcalviewer, ICAL_DESCRIPTION_PROPERTY);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_description(iprop), -1, NULL))
			tmp = conv_codeset_strdup(icalproperty_get_description(iprop), charset, CS_UTF_8);
		else
			tmp = g_strdup(icalproperty_get_description(iprop));
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), tmp);
		g_free(tmp);
		icalproperty_free(iprop);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->description), "-");
	}
	iprop = vcalviewer_get_property(vcalviewer, ICAL_URL_PROPERTY);
	g_free(vcalviewer->url);
	if (iprop) {
		if (!g_utf8_validate(icalproperty_get_url(iprop), -1, NULL))
			tmp = conv_codeset_strdup(icalproperty_get_url(iprop), charset, CS_UTF_8);
		else
			tmp = g_strdup(icalproperty_get_url(iprop));
		vcalviewer->url = g_strdup(tmp);
		g_free(tmp);
		icalproperty_free(iprop);
		gtk_widget_show(vcalviewer->uribtn);
	} else {
		vcalviewer->url = NULL;
		gtk_widget_hide(vcalviewer->uribtn);
	}

	iprop = vcalviewer_get_property(vcalviewer, ICAL_DTSTART_PROPERTY);
	if (iprop) {
		struct icaltimetype itt = (icalproperty_get_dtstart(iprop));
		time_t tmp = icaltime_as_timet(itt);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), ctime(&tmp));
		icalproperty_free(iprop);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->start), "-");
	}

	iprop = vcalviewer_get_property(vcalviewer, ICAL_DTEND_PROPERTY);
	if (iprop) {
		struct icaltimetype itt = (icalproperty_get_dtstart(iprop));
		time_t tmp = icaltime_as_timet(itt);
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), ctime(&tmp));
		icalproperty_free(iprop);
	} else {
		GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->end), "-");
	}

	GTK_LABEL_SET_TEXT_TRIMMED(GTK_LABEL(vcalviewer->attendees), "-"); 

	vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REPLY);
}

static void vcalviewer_get_info(VCalViewer *vcalviewer, MimeInfo *mimeinfo) 
{
	icalproperty *method = NULL;
	gboolean is_todo = FALSE;
	gchar *tmpfile = get_tmpfile(vcalviewer);
	
	if (vcalviewer->comp) {
		icalcomponent_free(vcalviewer->comp);
		vcalviewer->comp = NULL;
		vcalviewer->icomp = NULL;
	}
	
	if (!tmpfile) {
		vcalviewer_reset(vcalviewer);
		return;
	}

	vcalviewer->comp = vcalviewer_get_component(tmpfile);
	if (vcalviewer->comp)
		vcalviewer->icomp= icalcomponent_get_inner(vcalviewer->comp);
	else {
		vcalviewer_reset(vcalviewer);
		return;
	}
	
	method = vcalviewer_get_property(vcalviewer, ICAL_METHOD_PROPERTY);
	
	if (vcalviewer->icomp && icalcomponent_isa(vcalviewer->icomp) == ICAL_VTODO_COMPONENT)
		is_todo = TRUE;
debug_print("is_todo %d\n", is_todo);
	if (icalcomponent_isa(vcalviewer->comp) == ICAL_VCALENDAR_COMPONENT && method) {
		if (icalproperty_get_method(method) == ICAL_METHOD_REQUEST
		||  icalproperty_get_method(method) == ICAL_METHOD_PUBLISH
		||  icalproperty_get_method(method) == ICAL_METHOD_CANCEL)
			vcalviewer_get_request_values(vcalviewer, mimeinfo, is_todo);
		else if (icalproperty_get_method(method) == ICAL_METHOD_REPLY)
			vcalviewer_get_reply_values(vcalviewer, mimeinfo);
		else
			vcalviewer_reset(vcalviewer);
	} else if (is_todo && !method) {
		vcalviewer_get_request_values(vcalviewer, mimeinfo, is_todo);
	} else
		vcalviewer_reset(vcalviewer);
}

static VCalViewer *s_vcalviewer = NULL;

static void vcal_viewer_show_mimepart(MimeViewer *_mimeviewer, const gchar *file, MimeInfo *mimeinfo)
{
	VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;
	s_vcalviewer = vcalviewer;

	if (mimeinfo == NULL) {
		vcal_viewer_clear_viewer(_mimeviewer);
		return;
	}
	debug_print("vcal_viewer_show_mimepart : %s\n", file);

	vcal_viewer_clear_viewer(_mimeviewer);
	gtk_widget_show_all(vcalviewer->scrolledwin);
	g_free(vcalviewer->file);
	vcalviewer->file = g_strdup(file);
	vcalviewer->mimeinfo = mimeinfo;
	vcalviewer_get_info(vcalviewer, mimeinfo);
	GTK_EVENTS_FLUSH();
	gtk_widget_set_size_request(vcalviewer->description, 
		vcalviewer->scrolledwin->allocation.width - 200, -1);
	gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->summary), TRUE);
	gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->description), TRUE);
	gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
}

void vcalviewer_reload(void)
{
	if (s_vcalviewer) {
		debug_print("reload: %p, %p\n", (MimeViewer *)s_vcalviewer, s_vcalviewer->mimeinfo);
		vcal_viewer_show_mimepart((MimeViewer *)s_vcalviewer, NULL, s_vcalviewer->mimeinfo);
	}
}

static void vcal_viewer_destroy_viewer(MimeViewer *_mimeviewer)
{
	VCalViewer *vcalviewer = (VCalViewer *) _mimeviewer;

	debug_print("vcal_viewer_destroy_viewer\n");

	if (s_vcalviewer == vcalviewer)
		s_vcalviewer = NULL;
	vcal_viewer_clear_viewer(_mimeviewer);
	g_free(vcalviewer);
}

static gboolean vcalviewer_reedit_cb(GtkButton *widget, gpointer data)
{
	VCalViewer *vcalviewer = (VCalViewer *)data;
	gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
	VCalEvent *event = NULL;
	
	s_vcalviewer = vcalviewer;
	/* see if we have it registered and more recent */
	event = vcal_manager_load_event(uid);
	vcal_meeting_create(event);
	vcal_manager_free_event(event);
	return TRUE;
}

static gboolean vcalviewer_uribtn_cb(GtkButton *widget, gpointer data)
{
	VCalViewer *vcalviewer = (VCalViewer *)data;

	if (vcalviewer->url)
		open_uri(vcalviewer->url, prefs_common.uri_cmd);

	return TRUE;
}

static void refresh_folder_contents(VCalViewer *vcalviewer)
{
	Folder *folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
	if (folder) {
		MainWindow *mainwin = mainwindow_get_mainwindow();
		folder_item_scan(folder->inbox);
		folderview_check_new(folder);
		if (mainwin->summaryview->folder_item == folder->inbox)
			summary_show(mainwin->summaryview, folder->inbox);
	}
}
static gboolean vcalviewer_cancel_cb(GtkButton *widget, gpointer data)
{
	VCalViewer *vcalviewer = (VCalViewer *)data;
	gchar * uid = vcalviewer_get_uid_from_mimeinfo(vcalviewer->mimeinfo);
	VCalEvent *event = NULL;
	VCalMeeting *meet = NULL;
	gchar *file = NULL;
	gint val = 0;
	val = alertpanel_full(_("Cancel meeting"),
				   _("Are you sure you want to cancel this meeting?\n"
			           "A notification will be sent to attendees."),
				   GTK_STOCK_NO, GTK_STOCK_YES, NULL, FALSE,
				   NULL, ALERT_WARNING, G_ALERTDEFAULT);

	if (val != G_ALERTALTERNATE)
		return TRUE;
	
	s_vcalviewer = vcalviewer;
	
	event = vcal_manager_load_event(uid);
	if (!event)
		return TRUE;
	event->method = ICAL_METHOD_CANCEL;
	
	meet = vcal_meeting_create_hidden(event);
	if (!vcal_meeting_send(meet)) {
		event->method = ICAL_METHOD_REQUEST;
		vcal_manager_save_event(event);
		vcal_manager_free_event(event);
		refresh_folder_contents(vcalviewer);
		vcalviewer_reset(vcalviewer);
		return TRUE;
	}

	vcal_manager_save_event(event);
	
	file = vcal_manager_get_event_file(event->uid);
	unlink(file);
	vcal_manager_free_event(event);
	g_free(file);
	refresh_folder_contents(vcalviewer);
	vcalviewer_reset(vcalviewer);

	return TRUE;
}

static gboolean vcalviewer_action_cb(GtkButton *widget, gpointer data)
{
        VCalViewer *vcalviewer = (VCalViewer *)data;
	VCalEvent *event = NULL;
	icalproperty *iprop = NULL;
	gint index = gtk_combo_box_get_active(GTK_COMBO_BOX(vcalviewer->answer));
	enum icalparameter_partstat reply[3] = {ICAL_PARTSTAT_ACCEPTED, ICAL_PARTSTAT_TENTATIVE, ICAL_PARTSTAT_DECLINED};
	PrefsAccount *account = NULL;
	
	debug_print("index chosen %d\n", index);
	
	if (index < 0 || index > 2) {
		return TRUE;
	}
	
	s_vcalviewer = vcalviewer;

	iprop = vcalviewer_get_property(vcalviewer, ICAL_UID_PROPERTY);
	if (iprop) {
		event = vcal_manager_load_event(icalproperty_get_uid(iprop));
		icalproperty_free(iprop);
	}
	
	if (!event) {
		g_warning("can't get event\n");
		return TRUE;
	}
	account = get_account_from_attendees(vcalviewer);
	
	if (!account) {
		alertpanel_error (_("You have no account matching any attendee.\n"
				    "Have you really been invited?"));
		return TRUE;
	}
	
	vcal_manager_update_answer(event, account->address, account->name, reply[index], 0);
	
	if (!vcal_manager_reply(account, event)) {
		g_warning("couldn't send reply\n");
	}
	
	vcal_manager_free_event(event);
	
        return TRUE;
};

#define TABLE_ADD_LINE(label_text, widget) { 				\
	gchar *tmpstr = g_strdup_printf("<span weight=\"bold\">%s</span>",\
				label_text);				\
	GtkWidget *label = gtk_label_new(tmpstr);		 	\
	g_free(tmpstr);							\
	gtk_label_set_use_markup (GTK_LABEL (label), TRUE);		\
	gtk_misc_set_alignment (GTK_MISC(label), 1, 0);			\
	gtk_table_attach (GTK_TABLE (vcalviewer->table), 		\
			  label, 0, 1, i, i+1,				\
			  GTK_FILL, GTK_FILL, 6, 6);			\
	gtk_table_attach (GTK_TABLE (vcalviewer->table), 		\
			  widget, 1, 2, i, i+1,				\
			  GTK_FILL, GTK_FILL, 6, 6);			\
	if (GTK_IS_LABEL(widget)) {					\
		gtk_label_set_use_markup(GTK_LABEL (widget), TRUE);	\
		gtk_misc_set_alignment (GTK_MISC(widget),0, 0);		\
		gtk_label_set_line_wrap(GTK_LABEL(widget), TRUE);	\
	}								\
	i++;								\
}

MimeViewer *vcal_viewer_create(void)
{
	VCalViewer *vcalviewer;
	int i = 0;
	GtkWidget *hbox = NULL;
	GtkStyle *style;

	debug_print("Creating vcal view...\n");
	vcalviewer = g_new0(VCalViewer, 1);
	vcalviewer->mimeviewer.factory = &vcal_viewer_factory;

	vcalviewer->mimeviewer.get_widget = vcal_viewer_get_widget;
	vcalviewer->mimeviewer.show_mimepart = vcal_viewer_show_mimepart;
	vcalviewer->mimeviewer.clear_viewer = vcal_viewer_clear_viewer;
	vcalviewer->mimeviewer.destroy_viewer = vcal_viewer_destroy_viewer;
	
	vcalviewer->table = gtk_table_new(8, 2, FALSE);
	vcalviewer->type = gtk_label_new("meeting");
	vcalviewer->who = gtk_label_new("who");
	vcalviewer->start = gtk_label_new("start");
	vcalviewer->end = gtk_label_new("end");
	vcalviewer->summary = gtk_label_new("summary");
	vcalviewer->description = gtk_label_new("description");
	vcalviewer->attendees = gtk_label_new("attendees");
	vcalviewer->answer = gtk_combo_box_new_text();
	vcalviewer->url = NULL;
	vcalviewer->button = gtk_button_new_with_label(_("Answer"));
	vcalviewer->reedit = gtk_button_new_with_label(_("Edit meeting..."));
	vcalviewer->cancel = gtk_button_new_with_label(_("Cancel meeting..."));
	vcalviewer->uribtn = gtk_button_new_with_label(_("Launch website"));
	vcalviewer_answer_set_choices(vcalviewer, NULL, ICAL_METHOD_REQUEST);
	hbox = gtk_hbox_new(FALSE, 6);
	gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->answer, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->button, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->reedit, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->cancel, FALSE, FALSE, 0);
	gtk_box_pack_start(GTK_BOX(hbox), vcalviewer->uribtn, FALSE, FALSE, 0);
	
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->type), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->who), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->start), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->end), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->summary), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->description), TRUE);
	gtk_label_set_selectable(GTK_LABEL(vcalviewer->attendees), TRUE);
	
/*	gtk_widget_ensure_style(vcalviewer->who);
	style = gtk_style_copy
		(gtk_widget_get_style(vcalviewer->who));
	style->fg[GTK_STATE_NORMAL]   = uri_color;
	style->fg[GTK_STATE_ACTIVE]   = uri_color;
	style->fg[GTK_STATE_PRELIGHT] = uri_color;
	gtk_widget_set_style(vcalviewer->who, style);

	gtk_widget_ensure_style(vcalviewer->attendees);
	style = gtk_style_copy
		(gtk_widget_get_style(vcalviewer->attendees));
	style->fg[GTK_STATE_NORMAL]   = uri_color;
	style->fg[GTK_STATE_ACTIVE]   = uri_color;
	style->fg[GTK_STATE_PRELIGHT] = uri_color;
	gtk_widget_set_style(vcalviewer->attendees, style);
*/
	g_signal_connect(G_OBJECT(vcalviewer->button), "clicked",
			 G_CALLBACK(vcalviewer_action_cb), vcalviewer);

	g_signal_connect(G_OBJECT(vcalviewer->reedit), "clicked",
			 G_CALLBACK(vcalviewer_reedit_cb), vcalviewer);

	g_signal_connect(G_OBJECT(vcalviewer->cancel), "clicked",
			 G_CALLBACK(vcalviewer_cancel_cb), vcalviewer);

	g_signal_connect(G_OBJECT(vcalviewer->uribtn), "clicked",
			 G_CALLBACK(vcalviewer_uribtn_cb), vcalviewer);

	TABLE_ADD_LINE(_("Event:"), vcalviewer->type);
	TABLE_ADD_LINE(_("Organizer:"), vcalviewer->who);
	TABLE_ADD_LINE(_("Summary:"), vcalviewer->summary);
	TABLE_ADD_LINE(_("Starting:"), vcalviewer->start);
	TABLE_ADD_LINE(_("Ending:"), vcalviewer->end);
	TABLE_ADD_LINE(_("Description:"), vcalviewer->description);
	TABLE_ADD_LINE(_("Attendees:"), vcalviewer->attendees);
	gtk_label_set_line_wrap(GTK_LABEL(vcalviewer->attendees), FALSE);
	TABLE_ADD_LINE(_("Action:"), hbox);
	
	vcalviewer->scrolledwin = gtk_scrolled_window_new(NULL, NULL);
	gtk_scrolled_window_add_with_viewport(
		GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin), 
		vcalviewer->table);
	gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(vcalviewer->scrolledwin),
				       GTK_POLICY_NEVER,
				       GTK_POLICY_AUTOMATIC);
	
	gtk_widget_show_all(vcalviewer->scrolledwin);
	return (MimeViewer *) vcalviewer;
}

static gchar *content_types[] =
	{"text/calendar", NULL};
	
MimeViewerFactory vcal_viewer_factory =
{
	content_types,
	0,
	vcal_viewer_create,
};

static gint alert_timeout_tag = 0;
static gint scan_timeout_tag = 0;

static gint vcal_webcal_check(gpointer data)
{
	Folder *root = folder_find_from_name ("vCalendar", vcal_folder_get_class());

	if (prefs_common.work_offline)
		return TRUE;
	
	manual_update = FALSE;
	folderview_check_new(root);
	manual_update = TRUE;
	return TRUE;
}

void vcalendar_init(void)
{
	Folder *folder = NULL;
	GSList *events = NULL;
	GSList *cur = NULL;
	
	mimeview_register_viewer_factory(&vcal_viewer_factory);
	folder_register_class(vcal_folder_get_class());

	folder = folder_find_from_name ("vCalendar", vcal_folder_get_class());
	if (!folder) {
		folder = folder_new(vcal_folder_get_class(), "vCalendar", NULL);
		folder->klass->create_tree(folder);
		folder_add(folder);
		folder_scan_tree(folder, TRUE);
	}
	if (folder)
		folder_item_scan(folder->inbox);
	
	vcal_folder_gtk_init();
	vcal_prefs_init();

	alert_timeout_tag = gtk_timeout_add(60*1000, 
				(GtkFunction)vcal_meeting_alert_check, 
				(gpointer)NULL);
	scan_timeout_tag = gtk_timeout_add(3600*1000, 
				(GtkFunction)vcal_webcal_check, 
				(gpointer)NULL);
	if (prefs_common.enable_color) {
		gtkut_convert_int_to_gdk_color(prefs_common.uri_col,
				       &uri_color);
	}
}

void vcalendar_done(void)
{
	MainWindow *mainwin = mainwindow_get_mainwindow();
	FolderView *folderview = NULL;
	FolderItem *fitem = NULL;

	if (mainwin == NULL)
		return;
	folderview = mainwin->folderview;
	fitem = folderview->summaryview->folder_item;

	if (fitem && 
	    fitem->folder->klass == vcal_folder_get_class()) {
		folderview_unselect(folderview);
		summary_clear_all(folderview->summaryview);
	}

	mimeview_unregister_viewer_factory(&vcal_viewer_factory);
	folder_unregister_class(vcal_folder_get_class());
	vcal_folder_gtk_done();
	vcal_prefs_done();
	gtk_timeout_remove(alert_timeout_tag);
	alert_timeout_tag = 0;
	gtk_timeout_remove(scan_timeout_tag);
	scan_timeout_tag = 0;
}
