/*
 * 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 of the License, or (at your option) version 3.
 *
 * 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 the program; if not, see <http://www.gnu.org/licenses/>  
 *
 *
 * Authors:
 *		Srinivasa Ragavan <sragavan@novell.com>
 *
 * Copyright (C) 2009 Novell, Inc. (www.novell.com)
 *
 */

#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif
#include <glib/gi18n.h>
#include "mail-message-view.h"
#include "mail-view.h"
#if HAVE_WEBKIT
#include <webkit/webkit.h>
#include "em-webkit-stream.h"
#endif
#if HAVE_MOZILLA
#include <gtkmozembed.h>
#include "em-mozembed-stream.h"
#endif
#include "mail/mail-session.h"
#include "mail/mail-ops.h"
#include "misc/e-spinner.h"
#include <gdk/gdkkeysyms.h>
#include "mail/em-composer-utils.h"
#include "mail-shell.h"
#include <math.h>
#include <e-util/e-util.h>
#include <composer/e-composer-header-table.h>
#include "mail-utils.h"
#include "em-format-mail-display.h"

extern char *scolor_norm;
extern char *scolor_sel;
extern GdkColor *pcolor_fg_norm;
extern GdkColor *pcolor_fg_sel;
extern char *unread_image;
struct _MailComposerView;

void e_msg_composer_set_lite (void);
void mail_composer_view_replace_composer (struct _MailComposerView *, GtkWidget *composer);

struct  _MailMessageViewPrivate {
	CamelFolder *folder;
	const char *uid;
	GtkWidget *arrow;
	GtkWidget *focus;
//	GtkWidget *focus_composer;
	CamelMimeMessage *msg;
	CamelMessageInfoBase *info;
	GtkWidget *header_row;
	const char *active_color;
	int mode;
	GtkWidget *spinner;
	GtkWidget *spinner_label;
	GtkWidget *unread_image;
	char *bold[2];
	char *normal[2];
	CamelOperation *cancel;
	gboolean show_composer;
	GtkWidget *attach_area;
	GtkWidget *html_headers;
	GtkWidget *table_headers;

	char *folder_uri;
};

G_DEFINE_TYPE (MailMessageView, mail_message_view, GTK_TYPE_VBOX)

struct _EComposerHeaderTable *e_msg_composer_get_header_table (struct _EMsgComposer *);
	
enum {
	MESSAGE_RENDERED, 
	MESSAGE_SELECTED,
	MESSAGE_REMOVED,
	MESSAGE_LOADED,
	MESSAGE_REPLY,
	LAST_SIGNAL
};


static guint signals[LAST_SIGNAL] = { 0 };
#if NOT_USED
static const char *norm_color = "#d3d7cf";
static const char *sel_color = "#729fcf";
#endif
static void unread_toggled (GtkWidget *w, GdkEventButton *event, MailMessageView *mmv);
static void construct_reply_composer (MailMessageView *mmv, int mode);

static void
mail_message_view_init (MailMessageView  *shell)
{
	shell->priv = g_new0(MailMessageViewPrivate, 1);
	shell->priv->spinner = NULL;
	shell->priv->cancel = NULL;
	shell->type = MAIL_VIEW_MESSAGE;
	shell->uri = "mail://";
	shell->priv->mode = -2;
	shell->composer = NULL;
	shell->priv->show_composer = FALSE;
}

static void
mail_message_view_finalize (GObject *object)
{
	MailMessageView *shell = (MailMessageView *)object;
	MailMessageViewPrivate *priv = shell->priv;
	
	if (shell->priv->cancel) {
		camel_operation_cancel(shell->priv->cancel);
	}
	if (shell->composer)
		gtk_widget_destroy (shell->composer);
	g_object_unref (shell->efwd);
	g_free ((char *)priv->uid);
	g_free (priv->folder_uri);
	g_free (priv->normal[0]);
	g_free (priv->normal[1]);
	g_free (priv->bold[0]);
	g_free (priv->bold[1]);


	if (priv->msg)
		 camel_object_unref (priv->msg);
	camel_message_info_free (priv->info);
	g_free (priv);

	G_OBJECT_CLASS (mail_message_view_parent_class)->finalize (object);
}

static void
mail_message_view_class_init (MailMessageViewClass *klass)
{
	GObjectClass * object_class = G_OBJECT_CLASS (klass);

	mail_message_view_parent_class = g_type_class_peek_parent (klass);
	object_class->finalize = mail_message_view_finalize;

	signals[MESSAGE_RENDERED] =
		g_signal_new ("message-rendered",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (MailMessageViewClass , message_rendered),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__VOID,
			      G_TYPE_NONE, 0);	
	signals[MESSAGE_SELECTED] =
		g_signal_new ("message-selected",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (MailMessageViewClass , message_selected),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__VOID,
			      G_TYPE_NONE, 0);
	signals[MESSAGE_REMOVED] =
		g_signal_new ("message-removed",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (MailMessageViewClass , message_removed),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__VOID,
			     G_TYPE_NONE, 0);
	signals[MESSAGE_LOADED] =
		g_signal_new ("message-loaded",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (MailMessageViewClass , message_loaded),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__VOID,
			     G_TYPE_NONE, 0);
	signals[MESSAGE_REPLY] =
		g_signal_new ("message-reply",
			      G_OBJECT_CLASS_TYPE (object_class),
			      G_SIGNAL_RUN_FIRST,
			      G_STRUCT_OFFSET (MailMessageViewClass , message_reply),
			      NULL, NULL,
			      g_cclosure_marshal_VOID__VOID,
			      G_TYPE_NONE, 0);
}

static void
mmv_message_opened(CamelFolder *folder, const char *uid, CamelMimeMessage *msg, void *data, CamelException *ex)
{
	MailMessageView *shell = (MailMessageView *)data;
	shell->priv->cancel = NULL;
	mail_indicate_new_mail (FALSE);
	//gtk_widget_hide (shell->priv->table_headers);
	//gtk_widget_show (shell->priv->html_headers);
	em_format_mail_set_message_view ((EMFormatMail *)shell->efwd, shell, shell->body, shell->priv->html_headers);
	em_format_format((EMFormat *)shell->efwd, folder, uid, msg); 
	shell->priv->msg = msg;
	gtk_widget_hide (shell->priv->spinner);
	gdk_window_invalidate_rect (((GtkWidget *)shell)->window, NULL, TRUE);
	gtk_widget_queue_draw ((GtkWidget *)shell);

	//if (shell->priv->show_composer) {
	//	 construct_reply_composer (shell, REPLY_MODE_ALL);
	//	 shell->priv->show_composer = FALSE;
	//}
}

static void
mmv_invalidate_row (GtkWidget *w)
{
	int wid = w->allocation.width;
	int heig = w->allocation.height;
	GdkRectangle rect = {0, 0, wid, heig};
		
	gdk_window_invalidate_rect  (w->window, &rect, TRUE);	
}

static gboolean
mmv_focus_out (GtkWidget *w, GdkEventFocus *event, MailMessageView *mmv)
{
	gtk_widget_modify_fg (mmv->more_details, GTK_STATE_NORMAL, pcolor_fg_norm);
	gtk_widget_modify_fg (mmv->sub_details, GTK_STATE_NORMAL, pcolor_fg_norm);
	gtk_widget_modify_fg (mmv->date_details, GTK_STATE_NORMAL, pcolor_fg_norm);
	mmv->priv->active_color = scolor_norm;
	mmv_invalidate_row (mmv->priv->header_row);

	return FALSE;
}

static gboolean
mmv_focus_in (GtkWidget *w, GdkEventFocus *event, MailMessageView *mmv)
{
	 gtk_widget_modify_fg (mmv->more_details, GTK_STATE_NORMAL, pcolor_fg_sel);
	 gtk_widget_modify_fg (mmv->sub_details, GTK_STATE_NORMAL, pcolor_fg_sel);
	 gtk_widget_modify_fg (mmv->date_details, GTK_STATE_NORMAL, pcolor_fg_sel);
	mmv->priv->active_color = scolor_sel;
	mmv_invalidate_row (mmv->priv->header_row);

	return FALSE;
}

static void
mmv_show (MailMessageView *mmv)
{
	if (!mmv->priv->msg) {
		gtk_widget_show(mmv->priv->spinner);
		mmv->priv->cancel = mail_get_messagex(mmv->priv->folder, mmv->priv->uid, mmv_message_opened, mmv, mail_msg_fast_ordered_push);
	} else {
		//if (mmv->priv->show_composer && 0) {
		//	  construct_reply_composer (mmv, REPLY_MODE_ALL);
		//	  mmv->priv->show_composer = FALSE;
		// }
	}
	gtk_widget_show (mmv->body);
	gtk_widget_show_all (mmv->footer);
	gtk_widget_hide (mmv->discard);
	gtk_widget_hide (mmv->pop_out);
	gtk_arrow_set ((GtkArrow *)mmv->priv->arrow, GTK_ARROW_DOWN, GTK_SHADOW_NONE);				
	gdk_window_invalidate_rect (((GtkWidget *)mmv)->window, NULL, TRUE);
	gtk_widget_queue_draw ((GtkWidget *)mmv);
}

static void
mmv_hide (MailMessageView *mmv)
{
	gtk_arrow_set ((GtkArrow *)mmv->priv->arrow, GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
	gtk_widget_hide (mmv->body);
	gtk_widget_hide_all (mmv->footer);
	gtk_widget_hide (mmv->frame);
	gtk_widget_hide (mmv->cbox);

	if (mmv->comp_view)
		gtk_widget_hide (mmv->comp_view);
	if (GTK_WIDGET_VISIBLE(mmv->main_header)) {
		gtk_widget_hide (mmv->main_header);
		gtk_label_set_markup ((GtkLabel *)mmv->more_details, _("<u>show details</u>"));
	}			
	gdk_window_invalidate_rect (((GtkWidget *)mmv)->window, NULL, TRUE);
	gtk_widget_queue_draw ((GtkWidget *)mmv);
}

static void
mmv_collapse (MailMessageView *mmv)
{
	if (GTK_WIDGET_VISIBLE(mmv->body))
		mmv_hide(mmv);
	else
		mmv_show (mmv);

}

void
mail_message_view_show_message (MailMessageView *mmv, gboolean show_composer)
{
	 if (show_composer)
		  mmv->priv->show_composer = TRUE;
	mmv_show (mmv);
}

static void
mmv_delete (MailMessageView *mmv, gboolean del)
{
	 if (del) {
		 camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED ); 
	 	g_signal_emit (mmv, signals[MESSAGE_REMOVED], 0);
	 } else
		 camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_DELETED, 0 );
}

static void
mmv_junk  (MailMessageView *mmv, gboolean junk)
{
	 if (junk)
		  camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN);	 
	 else
		  camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN, CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN);
}

static void
mmv_read (MailMessageView *mmv, gboolean read)
{
	 if (read) {
		  camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
		  gtk_widget_set_sensitive (mmv->priv->unread_image, FALSE);
		  gtk_label_set_markup ((GtkLabel *)mmv->sub_details, mmv->priv->normal[0]);
		  gtk_label_set_markup ((GtkLabel *)mmv->date_details, mmv->priv->normal[1]);
	} else {
		  camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, 0);
		  gtk_widget_set_sensitive (mmv->priv->unread_image, TRUE);
		  gtk_label_set_markup ((GtkLabel *)mmv->sub_details, mmv->priv->bold[0]);
		  gtk_label_set_markup ((GtkLabel *)mmv->date_details, mmv->priv->bold[1]);
	}
}

static gboolean
mmv_key_press (GtkWidget *w, GdkEventKey *event, MailMessageView *mmv)
{
	 gboolean shift = event->state & GDK_SHIFT_MASK ? TRUE : FALSE;

	switch (event->keyval) {
	case GDK_Return:	
	case GDK_KP_Enter:
		mmv_collapse (mmv);
		break;
	case GDK_KP_Right:
	case GDK_Right:
		 if (event->state & GDK_SHIFT_MASK) {
			  if (!GTK_WIDGET_VISIBLE(mmv->main_header)) {
				   gtk_label_set_markup ((GtkLabel *)mmv->more_details, _("<u>hide details</u>"));
				   gtk_widget_show (mmv->main_header);
			  }
			  break;
		 }		 
		 if (!GTK_WIDGET_VISIBLE(mmv->body))
			mmv_show(mmv);
		break;
	case GDK_KP_Left:
	case GDK_Left:
		 if (event->state & GDK_SHIFT_MASK) {
			  if (GTK_WIDGET_VISIBLE(mmv->main_header)) {
				   gtk_widget_hide (mmv->main_header);
				   gtk_label_set_markup ((GtkLabel *)mmv->more_details, _("<u>show details</u>"));
			  }			  
			  break;
		 }
		if (GTK_WIDGET_VISIBLE(mmv->body))
			mmv_hide(mmv);
		break;
	 case GDK_D:
	 case GDK_d:		  
		  if (!(event->state & GDK_CONTROL_MASK))
			   return FALSE;
	 case GDK_Delete:
		  mmv_delete (mmv, !shift);
		  break;
	 case GDK_J:
	 case GDK_j:
		  mmv_junk (mmv, !shift);
		  break;
	 case GDK_M:
	 case GDK_m:
		  mmv_read(mmv, !shift);
		
	default:
		return FALSE;
	};
	return TRUE;
}

static void
mmv_collapse_view (GtkWidget *w, GdkEventButton *event, MailMessageView *mmv)
{
	mmv_collapse (mmv);
	gtk_widget_grab_focus (mmv->priv->focus);
	g_signal_emit (mmv, signals[MESSAGE_SELECTED], 0);			
}

static void
discard_composer_cb (GtkWidget *w, MailMessageView *mmv)
{
	gtk_widget_hide (mmv->frame);
	gtk_widget_hide (mmv->cbox);
	if (mmv->comp_view)
		gtk_widget_hide (mmv->comp_view);
	gtk_widget_hide (mmv->discard);
	gtk_widget_hide (mmv->pop_out);
	mmv->composer = NULL;
	gtk_widget_destroy (mmv->frame);
	mmv->frame = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type ((GtkFrame *)mmv->frame, GTK_SHADOW_IN);
	gtk_widget_destroy(mmv->cbox);
	mmv->cbox = gtk_hbox_new (FALSE, 0);

	/* FIXME: Destroy the composer in here */
}

static void
mmv_mail_send (struct _EMsgComposer *composer, MailMessageView *mmv)
{
	gtk_widget_hide (mmv->frame);
	gtk_widget_hide (mmv->cbox);
	gtk_widget_hide (mmv->comp_view);
	gtk_widget_hide (mmv->discard);
	gtk_widget_hide (mmv->pop_out);
	mmv->composer = NULL;
	gtk_widget_destroy (mmv->frame);
	mmv->frame = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type ((GtkFrame *)mmv->frame, GTK_SHADOW_IN);
	gtk_widget_destroy(mmv->cbox);
	mmv->cbox = gtk_hbox_new (FALSE, 0);

}

static void
popout_composer_cb (GtkWidget *w, MailMessageView *mmv)
{
	MailViewChild *mcv;

	gtk_widget_hide (mmv->frame);
	gtk_widget_hide (mmv->cbox);
	gtk_widget_hide (mmv->comp_view);
	gtk_widget_hide (mmv->discard);
	gtk_widget_hide (mmv->pop_out);
	mcv = mail_shell_create_composer ();
	mail_composer_view_replace_composer ((struct _MailComposerView *)mcv, mmv->composer);
	mmv->frame = gtk_frame_new (NULL);
	mmv->cbox = gtk_hbox_new (FALSE, 0);
	gtk_frame_set_shadow_type ((GtkFrame *)mmv->frame, GTK_SHADOW_IN);

	mmv->composer = NULL;
	mmv->comp_view = NULL;
	/* FIXME: Destroy the composer in here */
}

#ifdef NOT_USED
static gboolean
key_press_cb (GtkWidget *w, GdkEventKey *event, gpointer web)
{
	gpointer frame = webkit_web_view_get_main_frame (web);
	
	switch (event->keyval) {
	case GDK_Return:	
	case GDK_KP_Enter:
		if (!webkit_web_frame_is_cursor_at_blockquote (frame))
			return FALSE;
		webkit_web_frame_break_quote (frame);
		return TRUE;
	}
	return FALSE;	
}
#endif

static void
construct_reply_composer (MailMessageView *mmv, int mode)
{
	struct _EComposerHeaderTable *table;

	e_msg_composer_set_lite();

	if (mode != mmv->priv->mode)
		discard_composer_cb (NULL, mmv);
	if (!mmv->composer) {
		GtkWidget *box = gtk_vbox_new (FALSE, 0), *tmp;
		gtk_widget_show(box);
		
		if (mode != -1)
			mmv->composer = (GtkWidget *)em_utils_reply_to_message (mmv->priv->folder, mmv->priv->uid, mmv->priv->msg, mode, NULL);
		else 
			mmv->composer = (GtkWidget *)em_utils_forward_message (mmv->priv->msg, mmv->priv->folder_uri);
		mmv->comp_view = g_object_get_data((GObject *)mmv->composer,"vbox");
		gtk_widget_reparent (mmv->comp_view, box);
		gtk_widget_set_size_request (mmv->comp_view, -1, 400);	
		
		/* Trying to focus on the editor */
	//	editor = e_msg_composer_get_mail_editor (mmv->comp_view);
	//	web_view = mail_editor_get_webview (editor);
	//	g_signal_connect (web_view, "key-press-event", key_press_cb, web_view);

		/* Hide most of the basic headers. We'll add an option for enabling them later.
		   Our objective is to make the inline composer as sleek as it can get. 
		*/
		table = e_msg_composer_get_header_table ((struct _EMsgComposer *)mmv->composer);
		e_composer_header_table_set_header_visible (table, E_COMPOSER_HEADER_FROM, FALSE);
		e_composer_header_table_set_header_visible (table, E_COMPOSER_HEADER_SUBJECT, FALSE);
		gtk_container_add ((GtkContainer *)mmv->frame, box);
		tmp = gtk_alignment_new (0.5, 0.5, 1.0, 1.0);
		gtk_alignment_set_padding ((GtkAlignment *)tmp, 0, 0, 0, 20);
		gtk_widget_show (tmp);
		gtk_box_pack_start ((GtkBox *)mmv->cbox, tmp, FALSE, FALSE, 18);
		gtk_box_pack_start ((GtkBox *)mmv->cbox, mmv->frame, TRUE, TRUE, 6);
		gtk_box_pack_start ((GtkBox *)mmv, mmv->cbox, FALSE, FALSE, 6);
		g_signal_connect (mmv->composer, "send", G_CALLBACK(mmv_mail_send), mmv);
	}
	gtk_widget_show (mmv->discard);
	gtk_widget_show (mmv->pop_out);
	gtk_widget_show (mmv->frame);
	gtk_widget_show (mmv->cbox);
	gtk_widget_show (mmv->comp_view);

	g_signal_emit (mmv, signals[MESSAGE_REPLY], 0);
}

static void
invoke_reply_name_composer_cb (GtkWidget *w, MailMessageView *mmv)
{
	construct_reply_composer (mmv, REPLY_MODE_SENDER);
}

static void
invoke_reply_all_composer_cb (GtkWidget *w, MailMessageView *mmv)
{
	construct_reply_composer (mmv, REPLY_MODE_ALL);
}

static void
invoke_forward_composer_cb (GtkWidget *w, MailMessageView *mmv)
{
	construct_reply_composer (mmv, -1); /* Hack this to treat as Forward*/
}

static void
more_details_cb (GtkWidget *w, GdkEventButton *event, MailMessageView *mmv)
{
	if (!GTK_WIDGET_VISIBLE(mmv->main_header)) {
		gtk_label_set_markup ((GtkLabel *)mmv->more_details, _("<u>hide details</u>"));
		gtk_widget_show (mmv->main_header);
	} else {
		gtk_widget_hide (mmv->main_header);
		gtk_label_set_markup ((GtkLabel *)mmv->more_details, _("<u>show details</u>"));
	}
}

static char *
filter_date (time_t date)
{
	time_t nowdate = time(NULL);
	time_t yesdate;
	struct tm then, now, yesterday;
	char buf[26];
	gboolean done = FALSE;

	if (date == 0)
		return g_strdup (_("?"));

	localtime_r (&date, &then);
	localtime_r (&nowdate, &now);
	if (then.tm_mday == now.tm_mday &&
	    then.tm_mon == now.tm_mon &&
	    then.tm_year == now.tm_year) {
		e_utf8_strftime_fix_am_pm (buf, 26, _("Today %l:%M %p"), &then);
		done = TRUE;
	}
	if (!done) {
		yesdate = nowdate - 60 * 60 * 24;
		localtime_r (&yesdate, &yesterday);
		if (then.tm_mday == yesterday.tm_mday &&
		    then.tm_mon == yesterday.tm_mon &&
		    then.tm_year == yesterday.tm_year) {
			e_utf8_strftime_fix_am_pm (buf, 26, _("Yesterday %l:%M %p"), &then);
			done = TRUE;
		}
	}
	if (!done) {
		int i;
		for (i = 2; i < 7; i++) {
			yesdate = nowdate - 60 * 60 * 24 * i;
			localtime_r (&yesdate, &yesterday);
			if (then.tm_mday == yesterday.tm_mday &&
			    then.tm_mon == yesterday.tm_mon &&
			    then.tm_year == yesterday.tm_year) {
				e_utf8_strftime_fix_am_pm (buf, 26, _("%a %l:%M %p"), &then);
				done = TRUE;
				break;
			}
		}
	}
	if (!done) {
		if (then.tm_year == now.tm_year) {
			e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %l:%M %p"), &then);
		} else {
			e_utf8_strftime_fix_am_pm (buf, 26, _("%b %d %Y"), &then);
		}
	}
#if 0
#ifdef CTIME_R_THREE_ARGS
	ctime_r (&date, buf, 26);
#else
	ctime_r (&date, buf);
#endif
#endif

	return g_strdup (buf);
}

static void
mmv_set_flags (MailMessageView *mmv, guint32 mask, guint32 set)
{
	 camel_message_info_set_flags((CamelMessageInfo *)mmv->priv->info, mask, set);
}

static int
mark_mail_read  (GtkWidget *w, GdkEventExpose *event, MailMessageView *mmv)
{
	 if ((mmv->priv->info->flags & CAMEL_MESSAGE_SEEN) == 0)
		  mmv_set_flags (mmv, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
	 gtk_widget_set_sensitive (mmv->priv->unread_image, FALSE);
	 gtk_label_set_markup ((GtkLabel *)mmv->sub_details, mmv->priv->normal[0]);
	 gtk_label_set_markup ((GtkLabel *)mmv->date_details, mmv->priv->normal[1]);

	 g_signal_handlers_disconnect_by_func(w, mark_mail_read, mmv);
	 return FALSE;
}

#if HAVE_WEBKIT
static void
mmv_finished_loading_webkit (WebKitWebView  *webkitwebview, WebKitWebFrame *arg1, gpointer user_data)
{
	 MailMessageView *mmview = (MailMessageView *) user_data;
	// gtk_widget_hide (mmview->priv->table_headers);
	// gtk_widget_show (mmview->priv->html_headers);
	 gtk_widget_hide(mmview->priv->spinner);
#if HAVE_WEBKIT_PATCHED	 
	gtk_widget_set_size_request ((GtkWidget *)webkitwebview, -1, webkit_web_frame_get_height(arg1));
#endif	 
	/* Connect on expose, and mark mail as read on expose, when the mail is actually seen */
	g_signal_connect (webkitwebview, "expose-event" , G_CALLBACK(mark_mail_read), mmview);
	g_signal_emit (mmview, signals[MESSAGE_LOADED], 0);
	gdk_window_invalidate_rect (((GtkWidget *)mmview)->window, NULL, TRUE);
	gtk_widget_queue_draw ((GtkWidget *)mmview);
	g_signal_emit (mmview, signals[MESSAGE_RENDERED], 0);

	if (mmview->priv->show_composer) {
		 construct_reply_composer (mmview, REPLY_MODE_ALL);
		 mmview->priv->show_composer = FALSE;
	}
}

static void
mmv_finished_webkit (WebKitWebView  *webkitwebview, WebKitWebFrame *arg1, gpointer user_data)
{
	 MailMessageView *mmview = (MailMessageView *) user_data;
	 gtk_label_set_text ((GtkLabel *)mmview->priv->spinner_label, _("Formatting message"));
	 gtk_widget_show(mmview->priv->spinner);
}

static gboolean
mmv_button_press (GtkWidget *widget, GdkEventButton *event, gpointer data)
{
	if (event->button == 3)
		return TRUE;

	return FALSE;
}
#endif

#if HAVE_MOZILLA
static gboolean
mmv_finished_mozilla (GtkWidget *w, MailMessageView *mmv)
{
	g_signal_connect (w, "expose-event" , mark_mail_read, mmv);
	g_signal_emit (mmv, signals[MESSAGE_LOADED], 0);
	g_signal_emit (mmv, signals[MESSAGE_RENDERED], 0);
	return FALSE;
}
#endif

#define RADIUS 8

static void
draw_full_rounded_rectangle (cairo_t *cr, gdouble x, gdouble y, gdouble width, gdouble height)
{
  int radius = RADIUS;

  if (width < 1 || height < 1)
    return;

  /* this allows for calculating end co-ordinates */
  width--;
  height--;

  if (width < RADIUS * 2)
  {
    radius = width / 2;
  }
  else if (height < RADIUS * 2)
  {
    radius = height / 2;
  }

  cairo_line_to (cr, x, y + height - radius);
  cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
  cairo_arc (cr, x + width - radius, y + radius, radius, G_PI * 1.5, 0);
  cairo_arc (cr, x + width - radius, y + height - radius, radius,  0,  G_PI * 0.5 );
  cairo_line_to (cr, x +radius , y + height);
  cairo_arc (cr, x + radius, y + height - radius, radius, G_PI * 0.5, G_PI );
  cairo_move_to (cr, x + radius, y + height );

}

static void
draw_rounded_rectangle (cairo_t *cr, gdouble x, gdouble y, gdouble width, gdouble height)
{
  int radius = RADIUS;

  if (width < 1 || height < 1)
    return;

  /* this allows for calculating end co-ordinates */
  width--;
  height--;

  if (width < RADIUS * 2)
  {
    radius = width / 2;
  }
  else if (height < RADIUS * 2)
  {
    radius = height / 2;
  }

  cairo_line_to (cr, x, y + height - radius);
  cairo_arc (cr, x + radius, y + radius, radius, G_PI, G_PI * 1.5);
  cairo_arc (cr, x + width - radius, y + radius, radius, G_PI * 1.5, 0);
  cairo_line_to (cr, x + width, y + height);
  cairo_line_to (cr, x , y + height);
  cairo_line_to (cr, x , y + height - radius);

}

/* HACK: None of the themes pick the color for Arrow. So I draw it. Its reqd. 
 * to show the selected messages arrow on a different color. It isn't visible 
 * otherwise. This bit of code is reffered from gtk+/gtk/gtkstyle.c */
static int
mmv_arrow_expose (GtkWidget *widget, GdkEventExpose *event, MailMessageView *mmv)
{
	 if (GTK_WIDGET_DRAWABLE (widget))  {
		  GtkArrow *arrow = GTK_ARROW (widget);
		  GtkMisc *misc = GTK_MISC (widget);
		  GtkShadowType shadow_type;
		  gint width, height;
		  gint x, y;
		  gint extent;
		  gfloat xalign;
		  GtkArrowType effective_arrow_type;
		  gfloat arrow_scaling;
		  gboolean active = mmv->priv->active_color == scolor_sel ? TRUE : FALSE;

		  gtk_widget_style_get (widget, "arrow-scaling", &arrow_scaling, NULL);

		  width = widget->allocation.width - misc->xpad * 2;
		  height = widget->allocation.height - misc->ypad * 2;
		  extent = MIN (width, height) * arrow_scaling;
		  effective_arrow_type = arrow->arrow_type;

		  if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR)
			   xalign = misc->xalign;
		  else  {
			   xalign = 1.0 - misc->xalign;
			   if (arrow->arrow_type == GTK_ARROW_LEFT)
					effective_arrow_type = GTK_ARROW_RIGHT;
			   else if (arrow->arrow_type == GTK_ARROW_RIGHT)
					effective_arrow_type = GTK_ARROW_LEFT;
		  }

		  x = floor (widget->allocation.x + misc->xpad
					 + ((widget->allocation.width - extent) * xalign));
		  y = floor (widget->allocation.y + misc->ypad
					 + ((widget->allocation.height - extent) * misc->yalign));

		  shadow_type = arrow->shadow_type;

		  if (widget->state == GTK_STATE_ACTIVE) {
			   if (shadow_type == GTK_SHADOW_IN)
					shadow_type = GTK_SHADOW_OUT;
			   else if (shadow_type == GTK_SHADOW_OUT)
					shadow_type = GTK_SHADOW_IN;
			   else if (shadow_type == GTK_SHADOW_ETCHED_IN)
					shadow_type = GTK_SHADOW_ETCHED_OUT;
			   else if (shadow_type == GTK_SHADOW_ETCHED_OUT)
					shadow_type = GTK_SHADOW_ETCHED_IN;
		  }


		  widget->style->fg[widget->state] = active ? *pcolor_fg_sel : *pcolor_fg_norm; 
		  /* gtk_paint_arrow (widget->style, widget->window,
						   widget->state, shadow_type, 
						   &event->area, widget, "mrrow1", 
						   effective_arrow_type, TRUE, 
						   x, y, extent, extent); */
      
     
		  if (1)  {
			   GdkWindow *window = widget->window;    
			   GdkRectangle *area = &event->area;
			   GtkArrowType   arrow_type = effective_arrow_type;
			   width = height = extent;
			   cairo_t *cr = gdk_cairo_create (window);
			   gdk_cairo_set_source_color (cr, active ? pcolor_fg_sel : pcolor_fg_norm);
  
			   if (area)
			   {
					gdk_cairo_rectangle (cr, area);
					cairo_clip (cr);
			   }
    
			   if (arrow_type == GTK_ARROW_DOWN)
			   {
					cairo_move_to (cr, x,              y);
					cairo_line_to (cr, x + width,      y);
					cairo_line_to (cr, x + width / 2., y + height);
			   }
			   else if (arrow_type == GTK_ARROW_UP)
			   {
					cairo_move_to (cr, x,              y + height);
					cairo_line_to (cr, x + width / 2., y);
					cairo_line_to (cr, x + width,      y + height);
			   }
			   else if (arrow_type == GTK_ARROW_LEFT)
			   {
					cairo_move_to (cr, x + width,      y);
					cairo_line_to (cr, x + width,      y + height);
					cairo_line_to (cr, x,              y + height / 2.);
			   }
			   else if (arrow_type == GTK_ARROW_RIGHT)
			   {
					cairo_move_to (cr, x,              y);
					cairo_line_to (cr, x + width,      y + height / 2.);
					cairo_line_to (cr, x,              y + height);
			   }

			   cairo_close_path (cr);
			   cairo_fill (cr);

			   cairo_destroy (cr);	      
		  }
	 }

	 return TRUE;
}

static int
mmv_foot_color_expose (GtkWidget *w, GdkEventExpose *event, GtkWidget *widget)
{
	cairo_t *cr = gdk_cairo_create (widget->window);
	int wid = w->allocation.width;
	int heig = w->allocation.height;
	GdkColor colr;
	
	/* Color code received from the wireframe spec */
	gdk_color_parse ("#fdfbee", &colr);
	gdk_cairo_set_source_color (cr,  &colr);
	if (GTK_IS_HBOX(w))
		draw_full_rounded_rectangle (cr, w->allocation.x+3, w->allocation.y-3, wid-12, heig+6);

	cairo_fill (cr);
	cairo_destroy (cr);


	return FALSE;
}

static int
mmv_sh_color_expose (GtkWidget *w, GdkEventExpose *event, MailMessageView *mmv)
{
	cairo_t *cr = gdk_cairo_create (w->window);
	int wid = w->allocation.width;
	int heig = w->allocation.height;
	GdkColor colr;

	gdk_color_parse (mmv->priv->active_color, &colr);
	gdk_cairo_set_source_color (cr,  &colr);
	if (GTK_IS_HBOX(w))
		draw_rounded_rectangle (cr, 1, 0, wid-1, heig);
	else
		cairo_rectangle (cr, 0, 0, wid, heig-1);

	cairo_fill (cr);
	cairo_destroy (cr);


	return FALSE;
}


#if HAVE_WEBKIT

gint
mmv_nav (gpointer a, gpointer b, gpointer c, gpointer d)
{
	const char *uri = webkit_network_request_get_uri(c);

	if (strncmp(uri, "mailto:", 7) == 0)
		mail_shell_create_composer_mailto (uri);
	else
	        e_show_uri (NULL, uri);

	return WEBKIT_NAVIGATION_RESPONSE_IGNORE;
}

GtkWidget *
mmv_create_webview (MailMessageView *mmv, GtkWidget *box)
{
	WebKitWebView *web = (WebKitWebView *)webkit_web_view_new ();
	GtkWidget *scroll = gtk_scrolled_window_new (NULL, NULL);

	gtk_scrolled_window_set_policy ((GtkScrolledWindow *)scroll, GTK_POLICY_AUTOMATIC, GTK_POLICY_NEVER);
	gtk_widget_show(scroll);
	gtk_container_add ((GtkContainer *)scroll, (GtkWidget*)web);

	g_signal_connect (web, "load-started", G_CALLBACK(mmv_finished_webkit), mmv);
	g_signal_connect (web, "load-finished", G_CALLBACK(mmv_finished_loading_webkit), mmv);
	g_signal_connect (web, "button-press-event", G_CALLBACK (mmv_button_press), mmv);
	g_signal_connect (web, "navigation-requested", G_CALLBACK (mmv_nav), mmv);

	gtk_box_pack_start ((GtkBox *)box, scroll, FALSE, FALSE, 0);
	webkit_web_view_set_editable (web, FALSE);
	gtk_widget_show ((GtkWidget *)web);

	return (GtkWidget *)web;
}
#endif

#if HAVE_MOZILLA
GtkWidget *
mmv_create_mozview (MailMessageView *mmv, GtkWidget *box)
{
	GtkWidget *web;
	web = gtk_moz_embed_new ();

	g_signal_connect (web, "net_stop", mmv_finished_mozilla, mmv);

	gtk_box_pack_start ((GtkBox *)box, web, TRUE, TRUE, 0);
	gtk_widget_show (web);

	return web;
}
#endif

typedef struct {
	const char *renderer;
	GtkWidget * (*create_web_view) (MailMessageView *, GtkWidget *);
	void (*set_web_flags) (gpointer, int);
	CamelStream * (*create_web_stream) (gpointer , GtkWidget *);
	GtkWidget *(*get_body) (CamelStream *);
}MailRenderer;

static MailRenderer web_renderers[] = {
#if HAVE_WEBKIT	
	{ "webkit", mmv_create_webview , em_webkit_stream_set_flags, em_webkit_stream_new, em_webkit_stream_get_body},
#endif
#if HAVE_MOZILLA	
	{ "mozilla", mmv_create_mozview, em_mozembed_stream_set_flags, em_mozembed_stream_new, em_mozembed_stream_get_body},
#endif	
};

static MailRenderer *current_renderer = NULL;

static MailRenderer *
get_current_renderer()
{
	if (!current_renderer) {
		int i, len = G_N_ELEMENTS (web_renderers);
		char *rend = (char *)g_getenv("ANJAL_RENDERER");

		if (len == 0)
			g_assert(0);
		
		for(i=0; i<len && rend; i++) {
			if(strcmp(rend, web_renderers[i].renderer) == 0) {
				current_renderer = &web_renderers[i];
				break;
			}
		}
		if (!current_renderer) {
			g_message("Unable to find requested renderer, using the first one as default\n");
			current_renderer = &web_renderers[0];
		}
	}

	return current_renderer;		
}
GtkWidget *
mail_message_view_create_webview (MailMessageView *mmv, GtkWidget *box)
{
	MailRenderer *render = get_current_renderer();

	return render->create_web_view(mmv, box);
}

GtkWidget *
mail_message_view_get_body (CamelStream *stream)
{
	MailRenderer *render = get_current_renderer();
	
	return render->get_body(stream);
}

CamelStream *
mail_message_view_create_webstream (gpointer web, GtkWidget *w)
{
	MailRenderer *render = get_current_renderer();

	return render->create_web_stream(web, w);
}

void
mail_message_view_set_web_flags (gpointer web, int flags)
{
	MailRenderer *render = get_current_renderer();

	render->set_web_flags(web, flags);
}

#define EXPOSE(widget,mmv) 	g_signal_connect (widget, "expose-event", G_CALLBACK (mmv_sh_color_expose), mmv);
#define EXPOSE_HEADER(widget,mmv) 	g_signal_connect (widget, "expose-event", G_CALLBACK (mmv_foot_color_expose), mmv);

static void
unread_toggled (GtkWidget *w, GdkEventButton *event, MailMessageView *mmv)
{
	 if (camel_message_info_flags(mmv->priv->info) & CAMEL_MESSAGE_SEEN) {
		  mmv_set_flags(mmv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, 0);
		  gtk_widget_set_sensitive (mmv->priv->unread_image, TRUE);
		  gtk_label_set_markup ((GtkLabel *)mmv->sub_details, mmv->priv->bold[0]);
		  gtk_label_set_markup ((GtkLabel *)mmv->date_details, mmv->priv->bold[1]);
	 } else {
		  mmv_set_flags(mmv, CAMEL_MESSAGE_SEEN, CAMEL_MESSAGE_SEEN);
		  gtk_widget_set_sensitive (mmv->priv->unread_image, FALSE);
		  gtk_label_set_markup ((GtkLabel *)mmv->sub_details, mmv->priv->normal[0]);
		  gtk_label_set_markup ((GtkLabel *)mmv->date_details, mmv->priv->normal[1]);
	 }
}

static void
junk_clicked (GtkWidget *w, MailMessageView *mmv)
{
	 mmv_set_flags(mmv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_NOTJUNK|CAMEL_MESSAGE_JUNK_LEARN,
				   CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_JUNK|CAMEL_MESSAGE_JUNK_LEARN);
}

static void
delete_clicked (GtkWidget *w, MailMessageView *mmv)
{
	 mmv_set_flags(mmv, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED, CAMEL_MESSAGE_SEEN|CAMEL_MESSAGE_DELETED );
	 g_signal_emit (mmv, signals[MESSAGE_REMOVED], 0);
}

static gboolean 
unread_enter(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
{
	MailMessageView *mmv = user_data;
	if (camel_message_info_flags(mmv->priv->info) & CAMEL_MESSAGE_SEEN)
		gtk_widget_set_sensitive (mmv->priv->unread_image, TRUE);

	return FALSE;
}

static gboolean 
unread_leave(GtkWidget *widget, GdkEventCrossing *event, gpointer user_data)
{
	MailMessageView *mmv = user_data;

	if (camel_message_info_flags(mmv->priv->info) & CAMEL_MESSAGE_SEEN)
		gtk_widget_set_sensitive (mmv->priv->unread_image, FALSE);
	
	return FALSE;
}

void
mail_message_view_set_message (MailMessageView *mmview, CamelFolder *folder, const char *uri, const char *uid, gboolean show_composer)
{
	 GtkWidget *tmp,  *menu;
	 GdkPixbuf *img;
	CamelMessageInfoBase *info;
	GtkWidget *box, *header_row, *details_row;
	GtkWidget *reply, *reply_all, *forward;
	char *str ,**strv;

	gchar *boldmsg, *header_text;
	GtkTable *table;
	GtkWidget *vbox, *widget;
	int row = 0;

	mmview->priv->active_color = scolor_norm;
	
	/* FIXME: Ref & Use */
	mmview->priv->uid = g_strdup(uid);
	mmview->priv->folder = folder;
	mmview->priv->folder_uri = g_strdup (uri);

	box = gtk_vbox_new (FALSE, 0);
	gtk_widget_show (box);

	mmview->short_header = gtk_event_box_new ();
	//gtk_container_set_focus_child (mmview, mmview->short_header);
	g_signal_connect (mmview->short_header, "button-press-event", G_CALLBACK(mmv_collapse_view), mmview);

	info = (CamelMessageInfoBase *)camel_folder_get_message_info (folder, uid);
	mmview->priv->info = info;
	header_row = gtk_hbox_new (FALSE, 0);
	gtk_container_add ((GtkContainer *)mmview->short_header, header_row);
	gtk_widget_show (header_row);

	gtk_widget_set_size_request (header_row, -1, 28);

	gtk_box_pack_start ((GtkBox *)box, mmview->short_header, FALSE, FALSE, 0);

	details_row = gtk_hbox_new (FALSE, 0);
	gtk_widget_show (details_row);
	gtk_box_pack_start ((GtkBox *)box, details_row, FALSE, FALSE, 0);

//	gtk_container_add (mmview->short_header, box);
	
	/* To draw focus */
	mmview->priv->focus = gtk_button_new (); gtk_widget_show (mmview->priv->focus);
	g_signal_connect (mmview->priv->focus,  "focus-out-event", G_CALLBACK(mmv_focus_out), mmview);
	g_signal_connect (mmview->priv->focus,  "focus-in-event", G_CALLBACK(mmv_focus_in), mmview);
	g_signal_connect (mmview->priv->focus,  "key-press-event", G_CALLBACK(mmv_key_press), mmview);
	gtk_widget_set_size_request (mmview->priv->focus, 0, 0);
	gtk_box_pack_start ((GtkBox *)header_row, mmview->priv->focus, FALSE, FALSE, 0);
	mmview->priv->header_row = header_row;
	EXPOSE(header_row, mmview);
	
	mmview->priv->arrow = gtk_arrow_new (GTK_ARROW_RIGHT, GTK_SHADOW_NONE);
	gtk_widget_show (mmview->priv->arrow);
	gtk_box_pack_start ((GtkBox *)header_row, mmview->priv->arrow, FALSE, FALSE, 2);
	g_signal_connect (mmview->priv->arrow, "expose-event", G_CALLBACK(mmv_arrow_expose), mmview);
	tmp = gtk_event_box_new ();
	EXPOSE(tmp, mmview);
	mmview->priv->unread_image = gtk_image_new ();
	EXPOSE(mmview->priv->unread_image, mmview);
	gtk_image_set_from_pixbuf ((GtkImage *)mmview->priv->unread_image, mail_utils_get_icon("anjal-mail-new",GTK_ICON_SIZE_MENU));
	gtk_widget_show (mmview->priv->unread_image);
	if (camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN)
		gtk_widget_set_sensitive (mmview->priv->unread_image, FALSE);
	gtk_widget_show (tmp);
	gtk_container_add ((GtkContainer *)tmp, mmview->priv->unread_image);
	gtk_box_pack_start ((GtkBox *)header_row, tmp, FALSE, FALSE, 2);
	g_signal_connect (tmp, "button-press-event", G_CALLBACK(unread_toggled), mmview);
	g_signal_connect (tmp, "enter-notify-event", G_CALLBACK(unread_enter), mmview);
	g_signal_connect (tmp, "leave-notify-event", G_CALLBACK(unread_leave), mmview);

	str = (char *)camel_message_info_from(info);
	strv = g_strsplit (str, "<", 2);
	mmview->priv->normal[0] = g_strdup_printf("%s - %s", *strv, camel_message_info_subject(info));
	mmview->priv->bold[0] = g_strdup_printf("<b>%s - %s</b>", *strv, camel_message_info_subject(info));

	tmp = gtk_label_new (NULL);
	gtk_widget_modify_fg (tmp, GTK_STATE_NORMAL, pcolor_fg_norm);
	gtk_label_set_ellipsize ((GtkLabel *)tmp, PANGO_ELLIPSIZE_END);
	gtk_label_set_max_width_chars ((GtkLabel *)tmp, 40);
	mmview->sub_details = tmp;
	gtk_widget_show(tmp);
	if (camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN)
		gtk_label_set_markup ((GtkLabel *)mmview->sub_details, mmview->priv->normal[0]);
	else
		gtk_label_set_markup ((GtkLabel *)mmview->sub_details, mmview->priv->bold[0]);


	gtk_box_pack_start ((GtkBox *)header_row, tmp, FALSE, FALSE, 2);

	menu = gtk_button_new ();
	g_object_set (menu, "focus-on-click", FALSE, NULL);
	gtk_container_add ((GtkContainer *)menu, gtk_arrow_new (GTK_ARROW_DOWN, GTK_SHADOW_ETCHED_OUT));
	gtk_widget_show_all (menu);
	/* gtk_box_pack_end (header_row, menu, FALSE, FALSE, 2); */
	/*
	reply = gtk_button_new ();
	img = e_icon_factory_get_icon ("mail-reply-sender", E_ICON_SIZE_MENU);
	gtk_button_set_image (reply, gtk_image_new_from_pixbuf(img));
	gtk_button_set_label (reply, _("Reply"));
	gtk_widget_show_all (reply);
	gtk_box_pack_end (header_row, reply, FALSE, FALSE, 0);
	*/
	mmview->priv->normal[1] = filter_date(camel_message_info_date_sent(info));
	mmview->priv->bold[1] = g_strdup_printf("<b>%s</b>", mmview->priv->normal[1]);

	tmp = gtk_label_new (NULL);
	gtk_widget_modify_fg (tmp, GTK_STATE_NORMAL, pcolor_fg_norm);
	mmview->date_details = tmp;
	gtk_widget_show(tmp);
	gtk_box_pack_end ((GtkBox *)header_row, tmp, FALSE, FALSE, 6);
	if (camel_message_info_flags(info) & CAMEL_MESSAGE_SEEN)
		gtk_label_set_markup ((GtkLabel *)mmview->date_details, mmview->priv->normal[1]);
	else
		gtk_label_set_markup ((GtkLabel *)mmview->date_details, mmview->priv->bold[1]);
	
	mmview->details_event = gtk_event_box_new ();
	g_signal_connect (mmview->details_event, "button-press-event", G_CALLBACK(more_details_cb), mmview);
	mmview->more_details = gtk_label_new (_("<u>show details</u>"));
	gtk_widget_modify_fg (mmview->more_details, GTK_STATE_NORMAL, pcolor_fg_norm);
	gtk_container_add ((GtkContainer *)mmview->details_event, mmview->more_details);
	gtk_label_set_use_markup (GTK_LABEL (mmview->more_details), TRUE);
	EXPOSE(mmview->more_details, mmview);
	gtk_box_pack_end ((GtkBox *)header_row, mmview->details_event, FALSE, FALSE, 12);
	gtk_widget_show_all (mmview->details_event);
	

	
	gtk_widget_show(mmview->short_header);
	gtk_box_pack_start ((GtkBox *)mmview, box, FALSE, FALSE, 0);

	/* Full Headers */
	table = (GtkTable *) gtk_table_new (1, 2, FALSE);
	mmview->main_header = gtk_hbox_new (FALSE, 12);
	tmp = gtk_image_new_from_icon_name ("stock_person", GTK_ICON_SIZE_DIALOG);
	gtk_widget_show(tmp);
	mail_util_fill_photo (tmp, camel_message_info_from(info));
	gtk_box_pack_start ((GtkBox *)GTK_BOX (mmview->main_header), tmp, FALSE, FALSE, 3);

	mmview->priv->table_headers = (GtkWidget *)table;
	gtk_box_pack_start ((GtkBox *)GTK_BOX (mmview->main_header), GTK_WIDGET (table), TRUE, TRUE, 3);
	mmview->priv->html_headers = gtk_vbox_new (FALSE, 0);
	gtk_box_pack_start ((GtkBox *)GTK_BOX (mmview->main_header), GTK_WIDGET (mmview->priv->html_headers), TRUE, TRUE, 3);

	gtk_table_set_col_spacings (table ,12);
	gtk_table_set_row_spacings (table, 6);

	/* Name is in here */
	boldmsg = g_strdup_printf ("<b>%s</b>", _("From:"));
	widget = gtk_label_new (boldmsg);
	g_free (boldmsg);
	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
	gtk_table_attach (table, widget , 0, 1, row,  row + 1, GTK_FILL, 0, 0, 0);
	str = (char *)camel_message_info_from(info);
	widget = gtk_label_new (*strv);
	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
	gtk_table_attach (table, widget , 1, 2, row,  row + 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
	row++;

	/* The To field */
	boldmsg = g_strdup_printf ("<b>%s</b>", _("To:"));
	widget = gtk_label_new (boldmsg);
	g_free (boldmsg);
	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
	gtk_table_attach (table, widget , 0, 1, row,  row + 1, GTK_FILL, 0, 0, 0);
	widget = gtk_label_new (camel_message_info_to(info));
	g_object_set (widget, "wrap", TRUE, NULL);
	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
	gtk_table_attach (table, widget , 1, 2, row,  row + 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
	row++;

	/* The Cc field */
	header_text = (char *)camel_message_info_cc(info);
	if (header_text) {
		boldmsg = g_strdup_printf ("<b>%s</b>", _("Cc:"));
		widget = gtk_label_new (boldmsg);
		g_free (boldmsg);
		gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
		gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
		gtk_table_attach (table, widget , 0, 1, row,  row + 1, GTK_FILL, 0, 0, 0);
		widget = gtk_label_new (header_text);
		gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
		gtk_table_attach (table, widget , 1, 2, row,  row + 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
		row++;
	}

	/* Subject is in here */
	boldmsg = g_strdup_printf ("<b>%s</b>", _("Subject:"));
	widget = gtk_label_new (boldmsg);
	g_free (boldmsg);
	gtk_misc_set_alignment (GTK_MISC (widget), 1.0, 0.5);
	gtk_label_set_use_markup (GTK_LABEL (widget), TRUE);
	gtk_table_attach (table, widget , 0, 1, row,  row + 1, GTK_FILL, 0, 0, 0);
	widget = gtk_label_new (camel_message_info_subject(info));
	//gtk_label_set_line_wrap (widget, TRUE);
	//gtk_label_set_line_wrap_mode (widget, PANGO_WRAP_WORD_CHAR);
	//gtk_label_set_max_width_chars (widget, 50);
	gtk_misc_set_alignment (GTK_MISC (widget), 0.0, 0.5);
	gtk_table_attach (table, widget , 1, 2, row,  row + 1, GTK_FILL|GTK_EXPAND, 0, 0, 0);
	row++;

	/* Delete / junk buttons */
	vbox = gtk_vbox_new (FALSE, 2);
	gtk_box_pack_end ((GtkBox *)mmview->main_header, vbox, FALSE, FALSE, 0);
	tmp = gtk_button_new ();
	g_object_set (tmp, "focus-on-click", FALSE, NULL);
	g_signal_connect (tmp, "clicked", G_CALLBACK(delete_clicked), mmview);
	gtk_button_set_relief((GtkButton *)tmp, GTK_RELIEF_NONE);
	img = mail_utils_get_icon ("stock_delete", GTK_ICON_SIZE_BUTTON);
	gtk_button_set_label ((GtkButton *)tmp, _("Delete"));
	gtk_button_set_image ((GtkButton *)tmp, gtk_image_new_from_pixbuf(img));
	gtk_box_pack_start ((GtkBox *)vbox, tmp, FALSE, FALSE, 0);
	tmp = gtk_button_new  ();
	g_object_set (tmp, "focus-on-click", FALSE, NULL);
	g_signal_connect (tmp, "clicked", G_CALLBACK(junk_clicked), mmview);
	gtk_button_set_relief((GtkButton *)tmp, GTK_RELIEF_NONE);
	img = mail_utils_get_icon ("mail-mark-junk", GTK_ICON_SIZE_BUTTON);

	gtk_button_set_label ((GtkButton *)tmp, _("Junk"));
	gtk_button_set_image ((GtkButton *)tmp, gtk_image_new_from_pixbuf(img));
	gtk_box_pack_start ((GtkBox *)vbox, tmp, FALSE, FALSE, 0);
	
	gtk_box_pack_start ((GtkBox *)mmview, mmview->main_header, TRUE, TRUE, 0);
	gtk_widget_show_all (mmview->main_header);
	gtk_widget_hide (mmview->main_header);
	gtk_widget_hide (mmview->priv->html_headers);
	/* Default: Body would be hidden */
	mmview->body = gtk_vbox_new (FALSE, 0);
	gtk_box_pack_start ((GtkBox *)mmview->body, mmview->priv->attach_area, FALSE, FALSE, 0);

	//gtk_box_pack_start (header_row, mmview->priv->spinner, FALSE, FALSE, 0);
	//gtk_widget_hide (mmview->priv->spinner);

	tmp = gtk_label_new (_("Downloading message"));
	mmview->priv->spinner_label = tmp;
	vbox = gtk_hbox_new (FALSE, 0);
	gtk_box_pack_start ((GtkBox *)vbox, e_spinner_new_spinning_small_shown (), FALSE, FALSE, 3);
	gtk_box_pack_start ((GtkBox *)vbox, tmp, FALSE, FALSE, 3);
	gtk_widget_show(tmp);
	gtk_widget_hide (vbox);
	mmview->priv->spinner = vbox;
	gtk_box_pack_start ((GtkBox *)mmview->body, mmview->priv->spinner, FALSE, FALSE, 0);
	gtk_box_pack_start ((GtkBox *)mmview, mmview->body, FALSE, FALSE, 2);
	
	mmview->footer = gtk_hbox_new (FALSE, 0);
	gtk_box_pack_start ((GtkBox *)mmview, mmview->footer, FALSE, FALSE, 2);
	
	/* To translators: Reply to the sender. The format is replaced by the 
	   name of the sender.
	*/
	str = g_strdup_printf (_("Reply to %s"), *strv);
	reply = gtk_button_new_with_label (str);
	EXPOSE_HEADER(mmview->footer, reply);

	g_free (str);
	g_strfreev(strv);
	g_signal_connect (reply, "clicked", G_CALLBACK (invoke_reply_name_composer_cb), mmview);
//	EXPOSE(reply, bgcolor);
	gtk_box_pack_start ((GtkBox *)mmview->footer, reply, FALSE, FALSE, 12);

	reply_all = gtk_button_new_with_label (_("Reply All"));
	g_signal_connect (reply_all, "clicked", G_CALLBACK (invoke_reply_all_composer_cb), mmview);
//	EXPOSE(reply_all, bgcolor);
	gtk_box_pack_start ((GtkBox *)mmview->footer, reply_all, FALSE, FALSE, 12);

	forward = gtk_button_new_with_label (_("Forward"));
	g_signal_connect (forward, "clicked", G_CALLBACK (invoke_forward_composer_cb), mmview);	
//	EXPOSE(forward, bgcolor);
	gtk_box_pack_start ((GtkBox *)mmview->footer, forward, FALSE, FALSE, 12);

	mmview->discard = gtk_button_new_with_label (_("Discard"));
	g_signal_connect (mmview->discard, "clicked", G_CALLBACK (discard_composer_cb), mmview);
	gtk_widget_hide (mmview->discard);
	gtk_box_pack_end ((GtkBox *)mmview->footer, mmview->discard, FALSE, FALSE, 12);

	mmview->pop_out = gtk_button_new_with_label (_("Move to tab"));
	g_signal_connect (mmview->pop_out, "clicked", G_CALLBACK (popout_composer_cb), mmview);
	gtk_widget_show(mmview->pop_out);
	gtk_widget_hide (mmview->pop_out);
	gtk_box_pack_end ((GtkBox *)mmview->footer, mmview->pop_out, FALSE, FALSE, 12);

//	EXPOSE(discard, bgcolor);
	/* Hide this one be default */
	mmview->cbox = gtk_hbox_new (FALSE, 0);
	mmview->frame = gtk_frame_new (NULL);
	gtk_frame_set_shadow_type ((GtkFrame *)mmview->frame, GTK_SHADOW_IN);

	if (!(info->flags & CAMEL_MESSAGE_SEEN)) {
		 mmview->priv->show_composer = show_composer;
		// mmv_show(mmview);
	}
}

void
mail_message_view_construct (MailMessageView *mmview)
{
	GtkWidget *vbox = gtk_vbox_new (FALSE, 0);
	mmview->efwd = (GtkWidget *)em_format_mail_display_new ();
	((EMFormat *)mmview->efwd)->show_photo = FALSE;
	em_format_mail_display_set_attachment_pane ((EMFormatMailDisplay *)mmview->efwd, vbox);
	em_format_set_session ((EMFormat *)mmview->efwd, session);
	gtk_box_set_spacing ((GtkBox *)mmview, 0);
	mmview->priv->attach_area = vbox;
}

MailMessageView *
mail_message_view_new ()
{
	MailMessageView *mmview = g_object_new (MAIL_MESSAGE_VIEW_TYPE, NULL);
	mail_message_view_construct (mmview);
	
	return mmview;
}

GtkWidget *
mail_message_view_get_focus_widget (MailMessageView *mmv)
{
	return mmv->priv->focus;
};

gboolean
mail_message_view_get_unread(MailMessageView *mmv)
{
	return !(camel_message_info_flags(mmv->priv->info) & CAMEL_MESSAGE_SEEN);
}

