/*
  gyrus-session.c

  GYRUS -- GNOME Cyrus Administrator GConf sessions storage.

  Copyright (C) 2003-2004 Alejandro Valdes J.
  Copyright (C) 2003-2004 Jorge Bustos B.
  Copyright (C) 2003-2005 Claudio Saavedra V.

  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, see <http://www.gnu.org/licenses/>.
  
*/

#include <config.h>

#include <gio/gio.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>

#include "glib/gi18n.h"
#include "gyrus-common.h"
#include "gyrus-main-app.h"
#include "gyrus-admin.h"
#include "gyrus-session.h"

enum
{
	COLUMN_NAME,
	COLUMN_HOST,
	COLUMN_USER,
	COLUMN_PORT,
	COLUMN_SEP_CHAR,
	COLUMN_USETLS,
	NUM_COLUMN
};

/* Function Prototypes */
static void gyrus_session_add_session_to_treeview (GyrusSession *);
static void gyrus_session_set_defaults_from_session (GyrusSession *);
GyrusSession * gyrus_session_new_from_interface (void);
static void gyrus_session_set_treeview (void);
static GyrusSession * gyrus_session_get_selected_session (gboolean remove);
static void gyrus_session_open (GyrusSession *session, gpointer user_data);
static void gyrus_session_list_set_sensitive (gboolean sensitive);
static void gyrus_session_edit_load_interface (gpointer user_data);
void gyrus_session_load_gconf_settings (void);
static void gyrus_session_edit_session (GyrusSession *session);
static void gyrus_session_append_session (GyrusSession *session);
static void gyrus_session_select_session (GyrusSession *session);

static GSettings *settings = NULL;
static GtkWidget *window = NULL;
static GtkWidget *window_edit = NULL;
static GtkWidget *checkbutton_secure;
static GtkWidget *entry_host;
static GtkWidget *entry_user;
static GtkWidget *entry_passwd;
static GtkWidget *combobox_sep_char;
static GtkWidget *button_new;
static GtkWidget *button_open;
static GtkWidget *button_delete;
static GtkWidget *button_cancel;
static GtkWidget *button_properties;
static GtkWidget *spinbutton_port;
static GtkWidget *entry_name;
static GtkWidget *treeview_sessions;
static GtkTreeModel *model_sessions;
static GtkListStore *model_separator;

static GtkWidget *button_session_edit_ok;
static GtkWidget *button_session_edit_cancel;

/*
static void
gyrus_session_debug_print_stored_sessions (GSList *sessions)
{
	GSList *iter;
	gchar *tmp;
	for (iter = sessions; iter != NULL; iter = g_slist_next (iter)) {
		tmp = iter->data;
		g_print (": %s\n", tmp);
	}
}
*/

static void
gyrus_session_list_free (GSList *sessions)
{
	GSList *iter;
	for (iter = sessions; iter != NULL; iter = g_slist_next (iter)) {
		g_free (iter->data);
	}

	g_slist_free (sessions);
	sessions = NULL;
}
	
/*** module callbacks ***/

static void
gyrus_session_checkbutton_secure_toggled (GtkWidget *widget,
                                          gpointer data)
{
	g_return_if_fail (GTK_IS_SPIN_BUTTON (data));

	gtk_spin_button_set_value (GTK_SPIN_BUTTON (data),
			gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)) ?
				993 : 143);
}

static void
gyrus_session_edit_on_button_cancel_clicked (GtkWidget *widget,
					     gpointer user_data)
{
	gtk_widget_destroy (window_edit);
}

static void
gyrus_session_edit_on_button_ok_clicked (GtkWidget *widget,
					 gpointer user_data)
{
	void (*GyrusSessionEditedFunc)(GyrusSession *) = user_data;
	GyrusSession *session;
	session = gyrus_session_new_from_interface ();
	
	GyrusSessionEditedFunc (session);
	gtk_widget_destroy (window_edit);
	gyrus_session_select_session (session);
	gtk_widget_grab_focus (button_open);
	gyrus_session_free (session);
}

static void
gyrus_session_on_button_properties_clicked (GtkWidget *widget,
					    gpointer user_data)
{
	GyrusSession *session = gyrus_session_get_selected_session (FALSE);
	gyrus_session_edit_load_interface (user_data);
	gtk_window_set_title (GTK_WINDOW (window_edit), _("Edit session"));
	gtk_widget_set_sensitive (entry_name, FALSE);
	g_signal_connect (G_OBJECT (button_session_edit_ok), "clicked",
			  G_CALLBACK (gyrus_session_edit_on_button_ok_clicked),
			  gyrus_session_edit_session);
	gyrus_session_set_defaults_from_session (session);
	gyrus_session_free (session);
}

static void
gyrus_session_on_button_new_clicked (GtkWidget *widget,
				     gpointer user_data)
{
	gyrus_session_edit_load_interface (user_data);
	gtk_window_set_title (GTK_WINDOW (window_edit), _("New session"));
	g_signal_connect (G_OBJECT (button_session_edit_ok), "clicked",
			  G_CALLBACK (gyrus_session_edit_on_button_ok_clicked),
			  gyrus_session_append_session);
}

static void
gyrus_session_on_button_open_clicked (GtkWidget *widget,
				      gpointer user_data)
{
	GyrusSession *session = gyrus_session_get_selected_session (FALSE);
	gyrus_session_open (session, user_data);
	gyrus_session_free (session);
}

static void
gyrus_session_on_button_delete_session_clicked (GtkWidget *widget,
						gpointer user_data)
{
	gchar *path;
	GyrusSession *session = gyrus_session_get_selected_session (TRUE);	
	GSettings *psettings;
	GVariant *var, *item;
	GVariantIter *iter;
	GVariantBuilder builder;
	GSList *sessions = NULL, *element;

	var = g_settings_get_value (settings, "stored-sessions");
	g_variant_get (var, "as", &iter);
	while ((item = g_variant_iter_next_value (iter)))
	{
	        g_variant_get (item, "s", &path);
	        sessions = g_slist_append (sessions, g_strdup (path));
	        g_free (path);
	        g_variant_unref (item);
	}
	g_variant_iter_free (iter);
	g_variant_unref (var);

	element = g_slist_find_custom (sessions, session->name,
					       (GCompareFunc) g_ascii_strcasecmp);
	if (element) {
		g_free (element->data);
		sessions = g_slist_delete_link (sessions, element);
	}

	g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
	for (element = sessions; element; element = element->next)
	        g_variant_builder_add (&builder, "s", (gchar *) element->data);
	g_settings_set_value (settings, "stored-sessions",
	                      g_variant_builder_end (&builder));
	gyrus_session_list_free (sessions);
	
	path = g_strconcat (PATH_SESSIONS, session->name, "/", NULL);
	psettings = g_settings_new_with_path (SCHEMA, path);

	g_settings_delay (psettings);
	g_settings_reset (psettings, "host");
	g_settings_reset (psettings, "port");
	g_settings_reset (psettings, "user");
	g_settings_reset (psettings, "separator-char");
	g_settings_reset (psettings, "use-tls");
	g_settings_apply (psettings);

	g_free (path);
	g_object_unref (psettings);

	gyrus_session_list_set_sensitive (FALSE);
	gyrus_session_free (session);
}

static void
gyrus_session_on_button_cancel_clicked (GtkWidget *widget, gpointer user_data)
{
	gtk_widget_destroy (window);
}

static void
gyrus_session_on_row_activated (GtkTreeView       *tree_view,
				GtkTreePath       *path,
				GtkTreeViewColumn *column,
				gpointer           user_data)
{
	GyrusSession *session = gyrus_session_get_selected_session (FALSE);
	gyrus_session_open (session, user_data);
	gyrus_session_free (session);	
}

static void
gyrus_session_list_set_sensitive (gboolean sensitive)
{
	gtk_widget_set_sensitive (button_open, sensitive);
	gtk_widget_set_sensitive (button_delete, sensitive);
	gtk_widget_set_sensitive (button_properties, sensitive);
}

static void
gyrus_session_on_entry_changed (GtkEditable *editable,
				gpointer user_data)
{
	GtkWidget *widget = GTK_WIDGET (user_data);
	
	gboolean sensitive = 
		gyrus_gtk_entry_has_text (GTK_ENTRY (entry_name)) &&
		gyrus_gtk_entry_has_text (GTK_ENTRY (entry_host)) &&
/* 		gyrus_gtk_entry_has_text (GTK_ENTRY (entry_passwd) && */
		gyrus_gtk_entry_has_text (GTK_ENTRY (entry_user));

	gtk_widget_set_sensitive (widget, sensitive);
}

/* save changes in @session in gconf */
static void
gyrus_session_edit_session (GyrusSession *session)
{
	gchar *path;
	GSettings *psettings;
	
	path = g_strconcat (PATH_SESSIONS, session->name, "/", NULL);
	psettings = g_settings_new_with_path (SCHEMA, path);

	g_settings_delay (psettings);
	g_settings_set_string (psettings, "host", session->host);
	g_settings_set_int (psettings, "port", session->port);
	g_settings_set_string (psettings, "user", session->user);
	g_settings_set_string (psettings, "separator-char", session->sep_char);
	g_settings_set_boolean (psettings, "use-tls", session->usetls);
	g_settings_apply (psettings);

	g_free (path);
	g_object_unref (psettings);
	gyrus_session_load_gconf_settings();
}

static void
gyrus_session_append_session (GyrusSession *new)
{
	gchar *path;
	gchar *name;
	GSList *sessions = NULL, *element;
	GSettings *psettings;
	GVariant *var, *item;
	GVariantIter *iter;
	GVariantBuilder builder;
	
	g_return_if_fail (new != NULL);

	if (new->name == NULL)
	{
		gyrus_common_show_message (GTK_WINDOW (window),
					   GTK_MESSAGE_ERROR,
					   _("A session name is required."));
		return;
	}
	
	var = g_settings_get_value (settings, "stored-sessions");
	g_variant_get (var, "as", &iter);
	while ((item = g_variant_iter_next_value (iter)))
	{
	        g_variant_get (item, "s", &name);
	        sessions = g_slist_append (sessions, g_strdup (name));
	        g_free (name);
	        g_variant_unref (item);
	}
	g_variant_iter_free (iter);
	g_variant_unref (var);

	element = g_slist_find_custom (sessions, new->name,
						(GCompareFunc) g_ascii_strcasecmp);
	if (element) {
		gchar * msg = g_strdup_printf (_("Session named \"%s\" already exists."),
					       new->name);
		gyrus_common_show_message(GTK_WINDOW (window),
					  GTK_MESSAGE_ERROR, msg);
		g_free (msg);
		gyrus_session_list_free (sessions);
		return;
	}

	name = g_strdup (new->name);
	sessions = g_slist_append (sessions, (gpointer) name);
	
	g_variant_builder_init (&builder, G_VARIANT_TYPE ("as"));
	for (element = sessions; element; element = element->next)
	        g_variant_builder_add (&builder, "s", (gchar *) element->data);
	g_settings_set_value (settings, "stored-sessions",
	                      g_variant_builder_end (&builder));
	gyrus_session_list_free (sessions);
	
	path = g_strconcat (PATH_SESSIONS, new->name, "/", NULL);
	psettings = g_settings_new_with_path (SCHEMA, path);

	g_settings_delay (psettings);
	g_settings_set_string (psettings, "host", new->host);
	g_settings_set_int (psettings, "port", new->port);
	g_settings_set_string (psettings, "user", new->user);
	g_settings_set_string (psettings, "separator-char", new->sep_char);
	g_settings_set_boolean (psettings, "use-tls", new->usetls);
	g_settings_apply (psettings);

	g_free (path);
	g_object_unref (psettings);
	
	gyrus_session_load_gconf_settings();
}

static void
gyrus_session_set_defaults_from_session (GyrusSession *session)
{
	gint value = 0;

	g_return_if_fail (session);

	gtk_entry_set_text (GTK_ENTRY (entry_host), session->host);
	gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_port), (gdouble) session->port);
	gtk_entry_set_text (GTK_ENTRY (entry_user), session->user);
	gtk_entry_set_text (GTK_ENTRY (entry_name), session->name);

	if (strcmp (session->sep_char, ".") == 0)
		value = 0;
	else if (strcmp (session->sep_char, "/") == 0)
		value = 1;
	else if (strcmp (session->sep_char, "auto") == 0)
		value = 2;

	gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_sep_char), 
				  value);
	
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (checkbutton_secure),
	                              session->usetls);
}

GyrusSession *
gyrus_session_new_from_interface (void)
{
	GyrusSession *session = g_new (GyrusSession, 1);
	
	if (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry_host)), -1))
		session->host = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_host)));
	else
		session->host = NULL;
	
	session->port = gtk_spin_button_get_value_as_int (GTK_SPIN_BUTTON
							  (spinbutton_port));
	
	if (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry_user)), -1))
		session->user = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_user)));
	else
		session->user = NULL;
	
	if (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry_name)), -1))
		session->name = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_name)));
	else
		session->name = NULL;

	if (g_utf8_strlen (gtk_entry_get_text (GTK_ENTRY (entry_passwd)), -1))
		session->passwd = g_strdup (gtk_entry_get_text (GTK_ENTRY (entry_passwd)));
	else
		session->passwd = NULL;

	session->sep_char = gtk_combo_box_text_get_active_text (GTK_COMBO_BOX_TEXT (combobox_sep_char));
	if (!g_utf8_strlen (session->sep_char, -1))
		session->sep_char = g_strdup (".");
	else if (strcmp (session->sep_char, _("Autodetect")) == 0) {
		g_free (session->sep_char);
		session->sep_char = g_strdup ("auto");
	}
	
	session->usetls = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton_secure));
	
	return session;
}

/* adds a session to the list and to the treeview */
static void
gyrus_session_add_session_to_treeview (GyrusSession *session)
{
	GtkTreeIter iter;
	
	gtk_list_store_append (GTK_LIST_STORE (model_sessions), &iter);
	gtk_list_store_set (GTK_LIST_STORE (model_sessions), &iter,
			    COLUMN_NAME, session->name,
			    COLUMN_HOST, session->host,
			    COLUMN_USER, session->user,
			    COLUMN_PORT, session->port,
			    COLUMN_SEP_CHAR, session->sep_char,
			    COLUMN_USETLS, session->usetls,
			    -1);
}

static gboolean
gyrus_session_on_selection_changed (GtkTreeSelection *selection,
				    GtkTreeModel *model,
				    GtkTreePath *path,
				    gboolean path_currently_selected,
				    gpointer data)
{
	gyrus_session_list_set_sensitive (!path_currently_selected);
	return TRUE;
}

static gboolean
gyrus_session_treeview_on_key_press_event (GtkWidget *widget,
					   GdkEventKey *event,
					   gpointer user_data)
{
	GtkTreeSelection *selection;
	GtkTreeView *treeview = GTK_TREE_VIEW (widget);
	
	selection = gtk_tree_view_get_selection (treeview);
	
	if (gtk_tree_selection_count_selected_rows (selection) == 0)
		return FALSE;
	
	switch (event->keyval) {
	case GDK_KEY_Delete:
		gtk_button_clicked (GTK_BUTTON (button_delete));
		return TRUE;
	default:
		break;
	}
	
	return FALSE;
}

static gboolean
gyrus_session_on_key_press_event (GtkWidget *widget,
				  GdkEventKey *event,
				  gpointer user_data)
{
	/* I've used a switch/case here because I am thinking in possible future
	 key events */
	
	switch (event->keyval) {
	case GDK_KEY_Escape:
		gtk_button_clicked (GTK_BUTTON (button_cancel));
		return TRUE;
	default:
		break;
	}

	return FALSE;
}

static void
gyrus_session_set_treeview (void)
{
	GtkCellRenderer *renderer;
	GtkTreeViewColumn *column;
	GtkTreeSelection *selection;
	
	renderer = gtk_cell_renderer_text_new ();
	column = gtk_tree_view_column_new_with_attributes (_("Session"),
							   renderer,
							   "text",
							   COLUMN_NAME,
							   NULL);
	gtk_tree_view_column_set_sort_column_id (column, COLUMN_NAME);
	
	gtk_tree_view_append_column (GTK_TREE_VIEW (treeview_sessions),
				     column);
	selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_sessions));
	gtk_tree_selection_set_select_function (selection, 
						gyrus_session_on_selection_changed,
						NULL, NULL);
	
	g_signal_connect (G_OBJECT (treeview_sessions), "key-press-event",
			  G_CALLBACK (gyrus_session_treeview_on_key_press_event),
			  NULL);
}

static void
gyrus_session_create_model_sessions (void)
{
	GtkListStore *model;
	
	model = gtk_list_store_new (NUM_COLUMN,
				    G_TYPE_STRING,
				    G_TYPE_STRING,
				    G_TYPE_STRING,
				    G_TYPE_INT,
				    G_TYPE_STRING,
				    G_TYPE_BOOLEAN);
	
	model_sessions = GTK_TREE_MODEL (model);
}

static void
gyrus_session_create_model_separator (void)
{
	GtkTreeIter iter;

	model_separator = gtk_list_store_new (1,G_TYPE_STRING);

	gtk_list_store_append(GTK_LIST_STORE(model_separator), &iter);
	gtk_list_store_set (GTK_LIST_STORE(model_separator), &iter,0,".", -1);

	gtk_list_store_append(GTK_LIST_STORE(model_separator), &iter);
	gtk_list_store_set (GTK_LIST_STORE(model_separator), &iter,0,"/", -1);

	gtk_list_store_append(GTK_LIST_STORE(model_separator), &iter);
	gtk_list_store_set (GTK_LIST_STORE(model_separator), &iter,0, _("Autodetect"), -1);
}

/* If remove is TRUE, the selected item is removed from the array */
static GyrusSession *
gyrus_session_get_selected_session (gboolean remove)
{
	GtkTreeIter iter;
	GtkTreeSelection *selection;

	GyrusSession *session = g_new0 (GyrusSession, 1);
	
	selection =
		gtk_tree_view_get_selection(GTK_TREE_VIEW (treeview_sessions));
	
	if (!gtk_tree_selection_get_selected (selection, NULL, &iter))
		return NULL;
	
	gtk_tree_model_get (model_sessions, &iter,
			    COLUMN_NAME, &(session->name),
			    COLUMN_HOST, &(session->host),
			    COLUMN_USER, &(session->user),
			    COLUMN_PORT, &(session->port),
			    COLUMN_SEP_CHAR, &(session->sep_char),
			    COLUMN_USETLS, &(session->usetls),
			    -1);
	
	if (remove) {
		gtk_list_store_remove (GTK_LIST_STORE (model_sessions),
				       &iter);
	}
	
	return session;
}

static GyrusSession *
gyrus_session_get_with_name (const gchar *name)
{
	GyrusSession *aux = NULL;
	GSettings *psettings;
	gchar *path;

	aux = g_new0 (GyrusSession, 1);
	path = g_strconcat (PATH_SESSIONS, name, "/", NULL);
	psettings = g_settings_new_with_path (SCHEMA, path);
	
	aux->name = g_strdup (name);
	aux->host = g_settings_get_string (psettings, "host");
	aux->port = g_settings_get_int (psettings, "port");
	aux->user = g_settings_get_string (psettings, "user");
	aux->sep_char = g_settings_get_string (psettings, "separator-char");
	aux->usetls = g_settings_get_boolean (psettings, "use-tls");

	g_free (path);
	g_object_unref (psettings);

	return aux;
}

void
gyrus_session_load_gconf_settings (void)
{
	gchar *key;
	GyrusSession *session = NULL;
	GSList *sessions = NULL, *aux;
	GVariant *var, *item;
	GVariantIter *iter;

	gtk_tree_view_set_model (GTK_TREE_VIEW (treeview_sessions),
				 model_sessions);

	var = g_settings_get_value (settings, "stored-sessions");
	g_variant_get (var, "as", &iter);
	while ((item = g_variant_iter_next_value (iter)))
	{
	        g_variant_get (item, "s", &key);
	        sessions = g_slist_append (sessions, g_strdup (key));
	        g_free (key);
	        g_variant_unref (item);
	}
	g_variant_iter_free (iter);
	g_variant_unref (var);
	
	if (sessions != NULL)
	{
		gtk_list_store_clear (GTK_LIST_STORE (model_sessions));
		aux = sessions;
		do
		{
			session = gyrus_session_get_with_name ((gchar *) aux->data);
			gyrus_session_add_session_to_treeview (session);
			gyrus_session_free (session);
			aux = g_slist_next (aux);
		} while (aux != NULL);
	}
	gyrus_session_list_free (sessions);
}

static void
gyrus_session_open (GyrusSession *session, gpointer user_data)
{
	GyrusMainApp *app;

	g_return_if_fail (GYRUS_IS_MAIN_APP (user_data));

	app = GYRUS_MAIN_APP (user_data);

	if (!session->host || !strlen (session->host)) {
		gyrus_common_show_message(GTK_WINDOW (window),
					  GTK_MESSAGE_ERROR,
					  _("No host specified."));
		return;
	}
	gyrus_main_app_append_page (GYRUS_MAIN_APP (app), session);
	gtk_widget_destroy (GTK_WIDGET (window));
}

static void
gyrus_session_load_interface (gpointer user_data)
{
	GtkBuilder *builder;

	builder = gtk_builder_new ();
        gtk_builder_add_from_resource (builder, "/org/gnome/gyrus/sessions.xml", NULL);

	window = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_sessions"));
	
	treeview_sessions = GTK_WIDGET (gtk_builder_get_object (builder, "treeview_sessions"));
	button_new = GTK_WIDGET (gtk_builder_get_object (builder, "button_new"));
	button_open = GTK_WIDGET (gtk_builder_get_object (builder, "button_open"));
	button_delete = GTK_WIDGET (gtk_builder_get_object (builder, "button_delete"));
	button_cancel = GTK_WIDGET (gtk_builder_get_object (builder, "button_cancel"));
	button_properties = GTK_WIDGET (gtk_builder_get_object (builder, "button_properties"));
	
	/* connect signals */
	g_signal_connect (G_OBJECT (window), "delete_event",
			  G_CALLBACK (gtk_widget_destroy),
			  NULL);
	   
	g_signal_connect (G_OBJECT (button_open), "clicked",
			  G_CALLBACK (gyrus_session_on_button_open_clicked),
			  user_data);

	g_signal_connect (G_OBJECT (button_properties), "clicked",
			  G_CALLBACK (gyrus_session_on_button_properties_clicked),
			  user_data);
	
	g_signal_connect (G_OBJECT (button_new), "clicked",
			  G_CALLBACK (gyrus_session_on_button_new_clicked),
			  user_data);
	
	g_signal_connect (G_OBJECT (button_delete), "clicked",
			  G_CALLBACK (gyrus_session_on_button_delete_session_clicked),
			  NULL);

	g_signal_connect (G_OBJECT (button_cancel), "clicked",
			  G_CALLBACK (gyrus_session_on_button_cancel_clicked),
			  NULL);

	g_signal_connect (G_OBJECT (window), "key-press-event",
			  G_CALLBACK (gyrus_session_on_key_press_event),
			  NULL);

	g_signal_connect (G_OBJECT (treeview_sessions), "row-activated", 
			  G_CALLBACK (gyrus_session_on_row_activated), 
			  user_data);

	gyrus_session_set_treeview ();
	gyrus_session_list_set_sensitive (FALSE);
	gyrus_session_create_model_sessions ();
	gyrus_session_create_model_separator ();
}

static void
gyrus_session_edit_load_interface (gpointer user_data)
{
	GtkBuilder *builder;
	GtkCellRenderer *cell;
        
	builder = gtk_builder_new ();
        gtk_builder_add_from_resource (builder, "/org/gnome/gyrus/sessions_edit.xml", NULL);

	window_edit = GTK_WIDGET (gtk_builder_get_object (builder, "dialog_session_edit"));
	checkbutton_secure = GTK_WIDGET (gtk_builder_get_object (builder, "checkbutton_secure"));
	entry_host = GTK_WIDGET (gtk_builder_get_object (builder, "entry_host"));
	entry_user = GTK_WIDGET (gtk_builder_get_object (builder, "entry_user"));
	entry_passwd = GTK_WIDGET (gtk_builder_get_object (builder, "entry_passwd"));
	combobox_sep_char = GTK_WIDGET (gtk_builder_get_object (builder, "combobox_sep_char"));
	spinbutton_port = GTK_WIDGET (gtk_builder_get_object (builder, "spinbutton_port"));
	button_session_edit_ok = GTK_WIDGET (gtk_builder_get_object (builder, "button_session_edit_ok"));
	button_session_edit_cancel = GTK_WIDGET (gtk_builder_get_object (builder, "button_session_edit_cancel"));
	entry_name = GTK_WIDGET (gtk_builder_get_object (builder, "entry_name"));

	g_object_unref (builder);

	/* set model to combobox of mailbox hierarchy separator */
	gtk_combo_box_set_model (GTK_COMBO_BOX (combobox_sep_char), GTK_TREE_MODEL (model_separator));
	cell = gtk_cell_renderer_text_new();
	gtk_cell_layout_pack_start(GTK_CELL_LAYOUT (combobox_sep_char), cell, TRUE);
	gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT (combobox_sep_char), cell, "text", 0, NULL);

	gtk_spin_button_set_value (GTK_SPIN_BUTTON (spinbutton_port), 143);

	g_signal_connect (G_OBJECT (button_session_edit_cancel), "clicked",
			  G_CALLBACK (gyrus_session_edit_on_button_cancel_clicked),
			  NULL);

	g_signal_connect (G_OBJECT (checkbutton_secure), "toggled",
	                  G_CALLBACK (gyrus_session_checkbutton_secure_toggled),
	                  (gpointer) spinbutton_port);
	
	g_signal_connect (G_OBJECT (entry_host), "changed",
			  G_CALLBACK (gyrus_session_on_entry_changed),
			  button_session_edit_ok);

	g_signal_connect (G_OBJECT (entry_user), "changed",
			  G_CALLBACK (gyrus_session_on_entry_changed),
			  button_session_edit_ok);

	g_signal_connect (G_OBJECT (entry_passwd), "changed",
			  G_CALLBACK (gyrus_session_on_entry_changed),
			  button_session_edit_ok);

	g_signal_connect (G_OBJECT (entry_name), "changed",
			  G_CALLBACK (gyrus_session_on_entry_changed),
			  button_session_edit_ok);

	gtk_widget_set_sensitive (button_session_edit_ok, FALSE);

	gtk_combo_box_set_active (GTK_COMBO_BOX (combobox_sep_char), 0);

	gtk_window_set_modal (GTK_WINDOW (window_edit), TRUE);
	gtk_window_set_transient_for (GTK_WINDOW (window_edit), GTK_WINDOW (window));
	gtk_widget_grab_default (button_session_edit_ok);
}

/* show window sessions */
void 
gyrus_session_show_sessions (GtkWidget *widget G_GNUC_UNUSED,
			     gpointer user_data)
{
	GtkTreeIter iter;
	if (!settings)
	        settings = g_settings_new ("org.gnome.gyrus");
	gyrus_session_load_interface (user_data);
	gtk_window_set_modal (GTK_WINDOW (window), TRUE);
	gyrus_session_load_gconf_settings ();

	gtk_tree_sortable_set_sort_column_id (GTK_TREE_SORTABLE(model_sessions),
                                         COLUMN_NAME, GTK_SORT_ASCENDING);

	if (gtk_tree_model_get_iter_first (model_sessions, &iter)) {
		GtkTreeSelection *selection;
		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_sessions));
		gtk_tree_selection_select_iter (selection, &iter);
		gtk_widget_grab_focus (button_open);
	} else {
		gtk_widget_grab_focus (button_new);
	}
	gtk_widget_show (window);
}

static gboolean 
gyrus_session_seek_session (GtkTreeModel *model,
			    GtkTreePath *path,
			    GtkTreeIter *iter,
			    gpointer user_data)
{
	GyrusSession *session = (GyrusSession *) user_data;
	gchar *session_name;
	
	gtk_tree_model_get (model, iter,
			    COLUMN_NAME, &session_name,
			    -1);
	if (strcmp (session_name, session->name) == 0) {
		GtkTreeSelection *selection;
		selection = gtk_tree_view_get_selection (GTK_TREE_VIEW (treeview_sessions));
		gtk_tree_selection_select_iter (selection, iter);
		g_free (session_name);
		return TRUE;
	}
	else {
		g_free (session_name);
		return FALSE;
	}
}

/* Selects the given #GyrusSession in the list of the
   Sessions Dialog.
*/
static void
gyrus_session_select_session (GyrusSession *session)
{
	gtk_tree_model_foreach (model_sessions,
				gyrus_session_seek_session,
				session);
}

/* frees memory used for the GyrusSession structure */
void
gyrus_session_free (GyrusSession *session)
{

	g_return_if_fail (session);

	if (session->name)
		g_free (session->name);
	if (session->user)
		g_free (session->user);
	if (session->host)
		g_free (session->host);
	if (session->passwd)
		g_free (session->passwd);
	if (session->sep_char)
		g_free (session->sep_char);

	g_free (session);
	session = NULL;
}
