/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */

/*
 *  Copyright (C) 2004 Hiroyuki Ikezoe
 *  Copyright (C) 2003 - 2004 Takuro Ashie
 *  Copyright (C) 2004 Hidetaka Iwai
 *
 *  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, 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.
 */

#include "kz-smart-bookmark-folder-action.h"

#include <gdk/gdkkeysyms.h>

#include "gtk24backports.h"

#include "kazehakase.h"
#include "intl.h"
#include "utils/utils.h"
#include "gobject-utils.h"
#include "kz-entry.h"

enum {
	PROP_0,
	PROP_KZ_WINDOW,
	PROP_KZ_BOOKMARK,
  	PROP_TEXT
};

#define KZ_SMART_BOOKMARK_FOLDER_ACTION_BOOKMARK_KEY "KzSmartBookmarkFolderAction::Bookmark"

static void kz_smart_bookmark_folder_action_class_init   (KzSmartBookmarkFolderActionClass *class);
static void kz_smart_bookmark_folder_action_init         (KzSmartBookmarkFolderAction      *action);
static void kz_smart_bookmark_folder_action_dispose      (GObject      *obj);
static void kz_smart_bookmark_folder_action_set_property (GObject      *object,
						          guint         prop_id,
						          const GValue *value,
						          GParamSpec   *pspec);
static void kz_smart_bookmark_folder_action_get_property (GObject      *object,
						          guint         prop_id,
						          GValue       *value,
						          GParamSpec   *pspec);
static void kz_smart_bookmark_folder_action_activate     (GtkAction    *action);

static GtkWidget *create_tool_item                       (GtkAction    *action);
static void       connect_proxy                          (GtkAction    *action,
			                                  GtkWidget    *proxy);
static void       disconnect_proxy                       (GtkAction    *action,
			                                  GtkWidget    *proxy);

static void       cb_entry_changed                       (GtkEditable  *editable,
							  GtkAction    *action);
static gboolean   cb_entry_key_press                     (GtkWidget    *widget,
							  GdkEventKey  *event,
							  KzSmartBookmarkFolderAction *action);
static void       cb_entry_activate                      (GtkEntry     *entry,
							  GtkAction    *action);
static void       cb_button_clicked                      (GtkWidget    *widget,
							  KzSmartBookmarkFolderAction *action);
static void       sync_text                              (GtkAction    *action,
							  GParamSpec   *pspec,
							  GtkWidget    *proxy);
static GtkActionClass *parent_class = NULL;


KZ_OBJECT_GET_TYPE(kz_smart_bookmark_folder_action,
		   "KzSmartBookmarkFolderAction",
		   KzSmartBookmarkFolderAction,
		   kz_smart_bookmark_folder_action_class_init,
		   kz_smart_bookmark_folder_action_init,
		   GTK_TYPE_ACTION)


static void
kz_smart_bookmark_folder_action_class_init (KzSmartBookmarkFolderActionClass *klass)
{
	GObjectClass *object_class;
	GtkActionClass *action_class;

	parent_class  = g_type_class_peek_parent(klass);
	object_class  = G_OBJECT_CLASS(klass);
	action_class  = GTK_ACTION_CLASS(klass);

	object_class->set_property     = kz_smart_bookmark_folder_action_set_property;
	object_class->get_property     = kz_smart_bookmark_folder_action_get_property;
	object_class->dispose          = kz_smart_bookmark_folder_action_dispose;

	action_class->activate         = kz_smart_bookmark_folder_action_activate;
	action_class->connect_proxy    = connect_proxy;
	action_class->disconnect_proxy = disconnect_proxy;
	action_class->create_tool_item = create_tool_item;
	action_class->toolbar_item_type = GTK_TYPE_TOOL_ITEM;

	g_object_class_install_property
		(object_class,
		 PROP_KZ_WINDOW,
		 g_param_spec_object ("kz-window",
				      _("KzWindow"),
				      _("The KzWindow"),
				      KZ_TYPE_WINDOW,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property
		(object_class,
		 PROP_KZ_BOOKMARK,
		 g_param_spec_object ("kz-bookmark",
				      _("KzBookmark"),
				      _("The Bookmark object"),
				      KZ_TYPE_BOOKMARK,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));
	g_object_class_install_property(
		object_class,
		PROP_TEXT,
		g_param_spec_string("text",
				    _("Text"),
				    _("Text in entries."),
				    NULL,
				    G_PARAM_READWRITE));
}


static void
kz_smart_bookmark_folder_action_init (KzSmartBookmarkFolderAction *action)
{
	action->kz            = NULL;
	action->bookmark      = NULL;
}


static void
kz_smart_bookmark_folder_action_dispose (GObject *obj)
{
	KzSmartBookmarkFolderAction *action = KZ_SMART_BOOKMARK_FOLDER_ACTION(obj);

	if (action->kz)
	{
		g_object_unref(action->kz);
		action->kz = NULL;
	}
	if (action->bookmark)
	{
		g_object_unref(action->bookmark);
		action->bookmark = NULL;
	}

	if (action->text)
	{
		g_free (action->text);
		action->text = NULL;
	}

	if (G_OBJECT_CLASS(parent_class)->dispose)
		G_OBJECT_CLASS(parent_class)->dispose(obj);
}


static void
kz_smart_bookmark_folder_action_set_property (GObject         *object,
				       guint            prop_id,
				       const GValue    *value,
				       GParamSpec      *pspec)
{
	KzSmartBookmarkFolderAction *action = KZ_SMART_BOOKMARK_FOLDER_ACTION(object);
  
	switch (prop_id)
	{
	case PROP_KZ_WINDOW:
		action->kz = g_object_ref(g_value_get_object(value));
		break;
	case PROP_KZ_BOOKMARK:
		action->bookmark = g_object_ref(g_value_get_object(value));
		break;
	case PROP_TEXT:
		g_free(action->text);
		action->text = g_value_dup_string(value);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static void
kz_smart_bookmark_folder_action_get_property (GObject         *object,
				       guint            prop_id,
				       GValue          *value,
				       GParamSpec      *pspec)
{
	KzSmartBookmarkFolderAction *action = KZ_SMART_BOOKMARK_FOLDER_ACTION(object);

	switch (prop_id)
	{
	case PROP_KZ_WINDOW:
		g_value_set_object(value, action->kz);
		break;
	case PROP_KZ_BOOKMARK:
		g_value_set_object(value, action->bookmark);
		break;
	case PROP_TEXT:
		g_value_set_string(value, action->text);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static GtkWidget *
create_tool_item (GtkAction *action)
{
	GtkWidget *widget, *entry, *hbox;
	const gchar *title;
	GType toolbar_item_type;

	toolbar_item_type = GTK_ACTION_GET_CLASS(action)->toolbar_item_type;
	widget = GTK_WIDGET(g_object_new(toolbar_item_type, NULL));
	KzBookmark *bookmark = KZ_SMART_BOOKMARK_FOLDER_ACTION(action)->bookmark;

	hbox = gtk_hbox_new(FALSE, 0);
	gtk_container_add(GTK_CONTAINER(widget), hbox);
	gtk_widget_show(hbox);

	entry = kz_entry_new();
	gtk_box_pack_start(GTK_BOX(hbox), entry, TRUE, TRUE, 0);
	g_signal_connect(G_OBJECT(entry), "changed",
			 G_CALLBACK(cb_entry_changed), action);
	g_signal_connect(G_OBJECT(entry), "key-press-event",
			 G_CALLBACK(cb_entry_key_press), action);
	g_signal_connect(G_OBJECT(entry), "activate",
			 G_CALLBACK(cb_entry_activate), action);

	g_signal_connect_object(action, "notify::text",
				G_CALLBACK(sync_text),
				entry, 0);
	gtk_widget_show(entry);

	title = kz_bookmark_get_title(bookmark);
	kz_entry_set_backtext(KZ_ENTRY(entry), 
			      title);
	kz_entry_set_icon_from_stock(KZ_ENTRY(entry),
				     KZ_STOCK_SEARCH,
				     GTK_ICON_SIZE_MENU);
	
	{
		GList *children, *node;
		children = kz_bookmark_get_children(bookmark);
		for (node = children; node; node = g_list_next(node))
		{
			KzBookmark *child = node->data;
			GtkWidget *button;

			title = kz_bookmark_get_title(child);
			button = gtk_button_new_with_label(title);
			g_object_set_data(G_OBJECT(button), 
					  KZ_SMART_BOOKMARK_FOLDER_ACTION_BOOKMARK_KEY,
					  child);
			gtk_box_pack_start(GTK_BOX(hbox), button,
					   FALSE, FALSE, 0);
			g_signal_connect(G_OBJECT(button), "clicked",
					 G_CALLBACK(cb_button_clicked), action);
			gtk_widget_show(button);
		}
		g_list_free(children);
	}

	return widget;
}


static void
kz_smart_bookmark_folder_action_activate (GtkAction *action)
{
	KzSmartBookmarkFolderAction *smart_action;
	KzBookmark *bookmark;
	GList *children, *first;
	const gchar *uri;
	gchar *smart_uri;
	gboolean new_tab;

	g_return_if_fail(KZ_IS_SMART_BOOKMARK_FOLDER_ACTION(action));

	if (GTK_ACTION_CLASS(parent_class)->activate)
		GTK_ACTION_CLASS(parent_class)->activate(action);

	smart_action = KZ_SMART_BOOKMARK_FOLDER_ACTION(action);
	bookmark = smart_action->bookmark;

	children = kz_bookmark_get_children(bookmark);
	first = g_list_first(children);
	if (first)
		bookmark = first->data;
	g_list_free(children);

	uri = kz_smart_bookmark_folder_action_get_text(smart_action);
	smart_uri = kz_bookmark_get_smart_uri(bookmark, uri);

	KZ_CONF_GET("Global", "entry_open_in_new_tab", new_tab, BOOL);
	if (new_tab)
		kz_window_open_new_tab(smart_action->kz, smart_uri);
	else	
		kz_window_load_url(smart_action->kz, smart_uri);
	g_free(smart_uri);
}


static void
cb_entry_changed(GtkEditable *editable, GtkAction *action)
{
	GtkEntry *entry;
	const gchar *text;

	g_return_if_fail(GTK_IS_ENTRY(editable));

	entry = GTK_ENTRY(editable);
	text = gtk_entry_get_text(entry);

	g_object_set(G_OBJECT(action), "text", text, NULL);
}


static void
cb_entry_activate(GtkEntry *entry, GtkAction *action)
{
	g_return_if_fail(GTK_IS_ENTRY(entry));
	g_return_if_fail(KZ_IS_SMART_BOOKMARK_FOLDER_ACTION(action));

	gtk_action_activate(action);
}


static void
sync_text (GtkAction *action, GParamSpec *pspec, GtkWidget *proxy)
{
	g_return_if_fail(GTK_IS_ENTRY(proxy));

	g_signal_handlers_block_by_func(proxy,
					G_CALLBACK(cb_entry_changed),
					action);
	gtk_entry_set_text(GTK_ENTRY(proxy),
			   KZ_SMART_BOOKMARK_FOLDER_ACTION(action)->text);
	g_signal_handlers_unblock_by_func(proxy,
					  G_CALLBACK(cb_entry_changed),
					  action);
}


static void
connect_proxy (GtkAction *action, GtkWidget *proxy)
{
	GTK_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);
}


static void
disconnect_proxy (GtkAction *action, GtkWidget *proxy)
{
	GTK_ACTION_CLASS (parent_class)->disconnect_proxy (action, proxy);
}


KzSmartBookmarkFolderAction *
kz_smart_bookmark_folder_action_new (KzWindow *kz, KzBookmark *bookmark)
{
	KzSmartBookmarkFolderAction *action;
	gchar *name = g_strdup_printf("SmartBookmark:%p", bookmark);

	action = KZ_SMART_BOOKMARK_FOLDER_ACTION(
			g_object_new(KZ_TYPE_SMART_BOOKMARK_FOLDER_ACTION,
				     "name",        name,
				     "label",       _("Entry"),
				     "tooltip",     NULL,
				     "stock_id",    KZ_STOCK_SEARCH,
				     "kz-window",   kz,
				     "kz-bookmark", bookmark,
				     NULL));
	g_free(name);

	return action;
}


static gboolean
cb_entry_key_press (GtkWidget *widget, GdkEventKey *event,
		    KzSmartBookmarkFolderAction *action)
{
	gboolean newtab;
	KzBookmark *bookmark = action->bookmark;

	if ((event->keyval == GDK_Return || event->keyval == GDK_ISO_Enter) &&
	    (event->state == GDK_CONTROL_MASK))
	{
		const gchar *uri;
		gchar *smart_uri;

		g_return_val_if_fail(GTK_IS_ENTRY(widget), FALSE);

		if (kz_bookmark_is_folder(bookmark))
		{
			GList *children, *first;
			children = kz_bookmark_get_children(bookmark);
			first = g_list_first(children);
			if (first)
				bookmark = first->data;
			g_list_free(children);
		}

		KZ_CONF_GET("Global", "entry_open_in_new_tab", newtab, BOOL);

		uri = gtk_entry_get_text(GTK_ENTRY(widget));

		smart_uri = kz_bookmark_get_smart_uri(bookmark, uri);

		if (newtab)
			kz_window_load_url(action->kz, smart_uri);
		else 
			kz_window_open_new_tab(action->kz, smart_uri);
		g_free(smart_uri);

		return TRUE;
	}

	return FALSE;
}

static void 
cb_button_clicked (GtkWidget *widget, KzSmartBookmarkFolderAction *action)
{
	KzBookmark *bookmark;
	const gchar *uri;
	gchar *smart_uri;
	gboolean newtab;

	bookmark = g_object_get_data(G_OBJECT(widget), 
				     KZ_SMART_BOOKMARK_FOLDER_ACTION_BOOKMARK_KEY);

	KZ_CONF_GET("Global", "entry_open_in_new_tab", newtab, BOOL);

	uri = kz_smart_bookmark_folder_action_get_text(action);

	smart_uri = kz_bookmark_get_smart_uri(bookmark, uri);

	if (newtab)
		kz_window_load_url(action->kz, smart_uri);
	else 
		kz_window_open_new_tab(action->kz, smart_uri);
	g_free(smart_uri);
}


void
kz_smart_bookmark_folderaction_set_text (KzSmartBookmarkFolderAction *action,
				  	 const gchar *text)
{
	g_return_if_fail(KZ_IS_SMART_BOOKMARK_FOLDER_ACTION(action));

	g_object_set(action, "text", text, NULL);
}


const gchar *
kz_smart_bookmark_folder_action_get_text (KzSmartBookmarkFolderAction *action)
{
	g_return_val_if_fail(KZ_IS_SMART_BOOKMARK_FOLDER_ACTION(action), NULL);

	return action->text;
}

