/*
  gyrus-dialog-find-mailbox.h

  GYRUS -- GNOME Cyrus Administrator. Find mailbox dialog and engine.
  
  Copyright (C) 2004 Claudio Saavedra V. <csaavedra@alumnos.utalca.cl>

  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 <gtk/gtk.h>
#include <glib-object.h>
#include <gdk/gdkkeysyms.h>
#include <string.h>

#include "glib/gi18n.h"
#include "gyrus-common.h"
#include "gyrus-dialog-find-mailbox.h"
#include "gyrus-main-app.h"
#include "gyrus-admin.h"
#include "gyrus-admin-mailbox.h"

struct _GyrusDialogFindMailboxPrivate {
	GtkWidget *comboboxentry_mailbox;

	GtkWidget *checkbutton_entire_word;
	GtkWidget *checkbutton_wrap_around;

	GtkWidget *button_find;
	GtkWidget *button_close;

	GyrusAdmin *admin;
};

G_DEFINE_TYPE_WITH_PRIVATE (GyrusDialogFindMailbox, gyrus_dialog_find_mailbox,
                            GTK_TYPE_DIALOG);

static void gyrus_dialog_find_mailbox_finalize (GObject *object);

/* Callbacks */

static gboolean
gyrus_dialog_find_mailbox_kp (GtkWidget *widget,
			      GdkEventKey *event,
			      gpointer user_data)
{
	GyrusDialogFindMailbox *dialog;
	dialog = GYRUS_DIALOG_FIND_MAILBOX (user_data);
		
	switch (event->keyval) {
	case GDK_KEY_Return:
	case GDK_KEY_KP_Enter:
		gtk_button_clicked (GTK_BUTTON (dialog->priv->button_find));
		return TRUE;
	default:
		break;
	}
	return FALSE;
}

typedef enum {
	GYRUS_FIND_MODE_ENTIRE_WORD,
	GYRUS_FIND_MODE_PREFIX,
	GYRUS_FIND_MODE_ANY
} GyrusFindMode;

static gboolean
gyrus_dialog_find_mailbox_compare_with_method (const gchar *haystack,
					       const gchar *needle,
					       GyrusFindMode mode)
{
	switch (mode) {
	case GYRUS_FIND_MODE_ENTIRE_WORD:
		return (strcmp (haystack, needle) == 0);
	case GYRUS_FIND_MODE_PREFIX:
		return g_str_has_prefix (haystack, needle);
	case GYRUS_FIND_MODE_ANY:
		return (strstr (haystack, needle) != NULL);
	default:
		break;
	}
	return FALSE;
}

static void
gyrus_dialog_find_mailbox_on_button_find_clicked (GtkButton *button,
						  gpointer user_data)
{
	GtkTreeSelection *selection;
	GtkTreeView *treeview;
	GtkTreeModel *model;
	GtkTreeIter iter;
	GtkTreePath *path;
	gchar *mailbox;
	gboolean found, more_mailboxes, wrap_around, search_from_beginning;
	const gchar *key;
	GyrusFindMode mode;

	GyrusDialogFindMailbox *dialog = GYRUS_DIALOG_FIND_MAILBOX (user_data);
	GyrusAdmin *admin = GYRUS_ADMIN	(dialog->priv->admin);

	if (gtk_toggle_button_get_active
	    (GTK_TOGGLE_BUTTON (dialog->priv->checkbutton_entire_word))) {
		mode = GYRUS_FIND_MODE_ENTIRE_WORD;
	}
	else
		mode = GYRUS_FIND_MODE_ANY;

	wrap_around = gtk_toggle_button_get_active
		(GTK_TOGGLE_BUTTON (dialog->priv->checkbutton_wrap_around));

	key = gtk_entry_get_text
		(GTK_ENTRY
		 (gtk_bin_get_child (GTK_BIN
		   (GYRUS_DIALOG_FIND_MAILBOX
		    (user_data)->priv->comboboxentry_mailbox))));

	treeview = gyrus_admin_get_users_treeview (admin);
	selection = gtk_tree_view_get_selection (treeview);
	
	/* If no item is selected, start the search from the begin */
	if (!gtk_tree_selection_get_selected (selection, &model, &iter)) {
		gtk_tree_model_get_iter_first (model, &iter);
		search_from_beginning = TRUE;
	}
	else {
		gtk_tree_model_iter_next (model, &iter);
		search_from_beginning = FALSE;
	}
	
	do {
		gtk_tree_model_get (model, &iter,
				    COL_MAILBOX_BASENAME, &mailbox,
				    -1);
		
		if ((found = gyrus_dialog_find_mailbox_compare_with_method
		     (mailbox, key, mode)) == TRUE) {
			gtk_tree_selection_select_iter (selection, &iter);
			path = gtk_tree_model_get_path(model, &iter);
			gtk_tree_view_set_cursor (treeview,
						  path, NULL, FALSE);
		}
		
		g_free (mailbox);

		/* if 'wrap around' mode is selected allows starting over
		 again */
		more_mailboxes = gtk_tree_model_iter_next (model, &iter);
		if (!more_mailboxes && wrap_around  && !search_from_beginning) {
			gtk_tree_model_get_iter_first (model, &iter);
			more_mailboxes = TRUE;
			search_from_beginning = TRUE;
		}
		
	} while (!found && more_mailboxes);

	if (!found) {
		gchar *msg = g_strdup_printf (_("The text '%s' was not found "
						"in the mailbox list."), key);
		gyrus_common_show_message (GTK_WINDOW (dialog),
					   GTK_MESSAGE_INFO,
					   msg);
		g_free (msg);

	}

	g_object_unref (treeview);
}

static void
gyrus_dialog_find_mailbox_on_entry_changed (GtkComboBox *combo_box,
					   gpointer user_data)
{
	GyrusDialogFindMailbox *dialog = GYRUS_DIALOG_FIND_MAILBOX (user_data);
	gboolean sensitive = gyrus_gtk_entry_has_text
		(GTK_ENTRY (gtk_bin_get_child
	                    (GTK_BIN (dialog->priv->comboboxentry_mailbox))));
	gtk_widget_set_sensitive (dialog->priv->button_find, sensitive);
}

/* Private Methods */

static void
gyrus_dialog_find_mailbox_class_init (GyrusDialogFindMailboxClass *class)
{
	GObjectClass *gobject_class = G_OBJECT_CLASS (class);

	gyrus_dialog_find_mailbox_parent_class = g_type_class_peek_parent (class);
	gobject_class->finalize = gyrus_dialog_find_mailbox_finalize;
}

static void
gyrus_dialog_find_mailbox_init_get_widgets (GyrusDialogFindMailbox *dialog)
{
	GtkWidget *vbox_find;
	GtkBuilder *builder;

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

	vbox_find = GTK_WIDGET (gtk_builder_get_object (builder, "vbox_find"));
	
	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area
	                                  (GTK_DIALOG (dialog))), vbox_find);
	
	dialog->priv->button_close
	        = gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Close"),
	                                 GTK_RESPONSE_CANCEL);
	gtk_button_set_image (GTK_BUTTON (dialog->priv->button_close),
	                      gtk_image_new_from_icon_name ("window-close",
	                                                    GTK_ICON_SIZE_BUTTON));
	gtk_button_set_always_show_image (GTK_BUTTON
	                                  (dialog->priv->button_close),
	                                  TRUE);
	dialog->priv->button_find
	        = gtk_dialog_add_button (GTK_DIALOG (dialog), _("_Find"),
	                                 GTK_RESPONSE_ACCEPT);
	gtk_button_set_image (GTK_BUTTON (dialog->priv->button_find),
	                      gtk_image_new_from_icon_name ("edit-find",
	                                                    GTK_ICON_SIZE_BUTTON));
	gtk_button_set_always_show_image (GTK_BUTTON
	                                  (dialog->priv->button_find),
	                                  TRUE);

	dialog->priv->checkbutton_entire_word = GTK_WIDGET (gtk_builder_get_object (builder, "checkbutton_entire_word"));
	dialog->priv->checkbutton_wrap_around = GTK_WIDGET (gtk_builder_get_object (builder, "checkbutton_wrap_around"));
	dialog->priv->comboboxentry_mailbox = GTK_WIDGET (gtk_builder_get_object (builder, "comboboxentry_mailbox"));
}

static void
gyrus_dialog_find_mailbox_init_connect_signals (GyrusDialogFindMailbox *dialog)
{
	g_signal_connect (G_OBJECT (dialog->priv->button_find), "clicked",
			  G_CALLBACK (gyrus_dialog_find_mailbox_on_button_find_clicked),
			  dialog);

	g_signal_connect (gtk_bin_get_child
	                  (GTK_BIN (dialog->priv->comboboxentry_mailbox)),
			  "key-press-event", G_CALLBACK (gyrus_dialog_find_mailbox_kp), dialog);
	

	g_signal_connect_swapped (G_OBJECT (dialog->priv->button_close), "clicked",
				  G_CALLBACK (gtk_widget_destroy), dialog);

/*
	g_signal_connect (G_OBJECT (dialog->priv->checkbutton_quota), "toggled",
			  G_CALLBACK (gyrus_dialog_find_mailbox_on_checkbutton_toggled),
			  dialog);
*/
	g_signal_connect (dialog->priv->comboboxentry_mailbox,
			  "changed",
			  G_CALLBACK (gyrus_dialog_find_mailbox_on_entry_changed),
			  dialog);
/*	
	g_signal_connect (G_OBJECT (dialog->priv->entry_quota), "changed",
			  G_CALLBACK (gyrus_dialog_find_mailbox_on_entry_changed),
			  dialog);
*/
}

static void
gyrus_dialog_find_mailbox_init (GyrusDialogFindMailbox *dialog)
{
	GtkListStore *model;

	dialog->priv = g_new0 (GyrusDialogFindMailboxPrivate, 1);

	dialog->priv->admin = NULL;
	
	gtk_window_set_titlebar (GTK_WINDOW (dialog), NULL);
	gtk_window_set_title (GTK_WINDOW (dialog), _("Find mailbox"));
	gtk_window_set_resizable (GTK_WINDOW (dialog), FALSE);
	gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
	
	gyrus_dialog_find_mailbox_init_get_widgets (dialog);
	gyrus_dialog_find_mailbox_init_connect_signals (dialog);

	model = gtk_list_store_new (1, G_TYPE_STRING);
	
	gtk_combo_box_set_model (GTK_COMBO_BOX (dialog->priv->comboboxentry_mailbox),
				 GTK_TREE_MODEL (model));
	gtk_combo_box_set_entry_text_column (GTK_COMBO_BOX (dialog->priv->comboboxentry_mailbox),
					     0);
	
/*
        if we implement history for the search, here we must add the previous
	searched items. Is necesary to add the model to GyrusDialogFindMailboxPrivate?
*/	
/*
	gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->priv->comboboxentry_mailbox),
				   "Foo.Bar");
*/

	gtk_widget_set_can_default (dialog->priv->button_find, TRUE);
	gtk_widget_grab_default (dialog->priv->button_find);

	gtk_widget_set_sensitive (dialog->priv->button_find, FALSE);
	gtk_widget_show_all (GTK_WIDGET (dialog));
}

static void
gyrus_dialog_find_mailbox_finalize (GObject *object)
{
	GyrusDialogFindMailbox *dialog_find_mailbox;
	g_return_if_fail (GYRUS_IS_DIALOG_FIND_MAILBOX(object));
	dialog_find_mailbox = GYRUS_DIALOG_FIND_MAILBOX (object);

	g_object_unref (G_OBJECT (dialog_find_mailbox->priv->admin));

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

GtkWidget *
gyrus_dialog_find_mailbox_new (void)
{
	GyrusDialogFindMailbox *dialog;
	dialog = g_object_new (GYRUS_TYPE_DIALOG_FIND_MAILBOX, NULL);
	return GTK_WIDGET (dialog);
}

/* Public Methods */

void
gyrus_dialog_find_mailbox_set_admin (GyrusDialogFindMailbox *dialog,
				     GyrusAdmin *admin)
{
	if (dialog->priv->admin)
		g_object_unref (G_OBJECT (dialog->priv->admin));
	
	dialog->priv->admin = g_object_ref (admin);
}
