/*
 *  Copyright (C) 2003 Ricardo Fernández Pascual
 *
 *  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.
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <gtk/gtktoolitem.h>

#include "galeon-action-location.h"
#include "gul-gobject-misc.h"
#include "location-entry.h"
#include "galeon-shell.h"
#include <glib/gi18n.h>
#include <string.h>

static void		galeon_action_location_init			(GaleonAction *action);
static void		galeon_action_location_class_init		(GaleonActionClass *class);
static void		galeon_action_location_connect_proxy		(GtkAction *action, GtkWidget *proxy);
static void		galeon_action_location_update			(GaleonAction *action);
static void		galeon_action_location_current_embed_changed	(GaleonAction *action, 
									 GaleonEmbed *old_embed, GaleonEmbed *new_embed);
static GtkWidget *	galeon_action_location_create_toolitem		(GtkAction *action);

static GtkActionClass *parent_class = NULL;

MAKE_GET_TYPE (galeon_action_location, "GaleonActionLocation", GaleonActionLocation, galeon_action_location_class_init, 
	       galeon_action_location_init, GALEON_TYPE_ACTION);


static void
galeon_action_location_class_init (GaleonActionClass *class)
{
	GtkActionClass *action_class = GTK_ACTION_CLASS (class);
	GaleonActionClass *galeon_action_class = GALEON_ACTION_CLASS (class);

	action_class->create_tool_item = galeon_action_location_create_toolitem;
	action_class->connect_proxy = galeon_action_location_connect_proxy;

	galeon_action_class->update = galeon_action_location_update;
	galeon_action_class->current_embed_changed = galeon_action_location_current_embed_changed;

	parent_class = g_type_class_peek_parent (class);
}

static void
galeon_action_location_init (GaleonAction *action)
{
	g_object_set (G_OBJECT (action), "tooltip", _("Enter location"), NULL);
	g_object_set (G_OBJECT (action), "label", _("Location"), NULL);
}

static const gchar * 
galeon_action_location_get_tab_location (GaleonAction *action)
{
	GaleonWindow *window = galeon_action_get_window (action);
	if (window)
	{
		GaleonTab *tab = galeon_window_get_active_tab (window);
		if (tab)
		{
			const gchar *location = galeon_tab_get_location (tab);
			return location ? location : "";
		}
		else
		{
			return "";
		}
	}
	else
	{
		return "";
	}
}

static void
galeon_action_location_update (GaleonAction *action)
{
	const gchar *location = galeon_action_location_get_tab_location (action);
	GSList *sli;
	
	if (!strcmp (location, "about:blank"))
	{
		location = "";
	}
	
	for (sli = gtk_action_get_proxies (GTK_ACTION (action)); sli; sli = sli->next)
	{
		GaleonLocationEntry *gle = GALEON_LOCATION_ENTRY (GTK_BIN (sli->data)->child);
		galeon_location_entry_set_location (gle, location);
	}
}

static void
galeon_action_location_location_cb (GaleonEmbed *embed, GaleonAction *action)
{
	galeon_action_location_update (action);
}

static void
galeon_action_location_current_embed_changed (GaleonAction *action, 
					      GaleonEmbed *old_embed, GaleonEmbed *new_embed)
{
	if (old_embed)
	{
		g_signal_handlers_disconnect_matched (old_embed, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, action);
	}

	if (new_embed)
	{
		g_signal_connect_object (new_embed, "ge-location", 
					 G_CALLBACK (galeon_action_location_location_cb), 
					 action, 0);
	}

	galeon_action_location_update (action);
}

static void
galeon_action_location_url_activate_cb (GaleonLocationEntry *entry, const gchar *url,
					gboolean new_tab_or_window, GaleonActionLocation *action)
{
	GbBookmarkSet *set;
	gchar *real_url;
	GaleonWindow *window = galeon_action_get_window (GALEON_ACTION (action));
	GaleonTab *tab;

	if (!new_tab_or_window)
	{
		/* galeon_window_load_url handles bookmark nicks */
		galeon_window_load_url (window, url);
		return;
	}

	set = galeon_shell_get_bookmark_set (galeon_shell);
	real_url = gb_bookmark_set_get_url_by_nick_and_args (set, url);

	/* Open the link in a new tab (or window) */
	tab = galeon_window_get_active_tab (window);
	galeon_shell_new_tab (galeon_shell, window, tab, 
			      real_url != NULL ? real_url : url, 0);
	
	g_free (real_url);
}

static gboolean
toolitem_create_menu_proxy_cb (GtkToolItem *toolitem, gpointer dummy)
{
	/* Don't show item in overflow menu */
	gtk_tool_item_set_proxy_menu_item (toolitem, "galeon-location-menu-item", NULL);
	return TRUE;
}

static GtkWidget *
galeon_action_location_create_toolitem (GtkAction *action)
{
	GaleonAutocompletion *ac = galeon_shell_get_autocompletion (galeon_shell);
	GtkToolItem *ti = gtk_tool_item_new ();
	GaleonLocationEntry *gle = galeon_location_entry_new ();
	gtk_container_add (GTK_CONTAINER (ti), GTK_WIDGET (gle));
	gtk_widget_show (GTK_WIDGET (gle));
	gtk_tool_item_set_expand (ti, TRUE);

	galeon_location_entry_set_autocompletion (gle, ac);

	g_signal_connect (gle, "url-activated",
			  G_CALLBACK (galeon_action_location_url_activate_cb), action);
	g_signal_connect (ti, "create-menu-proxy",
			  G_CALLBACK (toolitem_create_menu_proxy_cb), NULL);

	return GTK_WIDGET (ti);
}

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

void
galeon_action_location_edit (GaleonActionLocation *action)
{
	GSList *sli;
	for (sli = gtk_action_get_proxies (GTK_ACTION (action)); sli; sli = sli->next)
	{
		GaleonLocationEntry *gle = GALEON_LOCATION_ENTRY (GTK_BIN (sli->data)->child);
		galeon_location_entry_edit (gle);
	}
}

/**
 * This returns the text of the first proxy, or "" if there is no
 * proxy. Usually, there should be only one proxy.
 */
gchar *
galeon_action_location_get_location (GaleonActionLocation *action)
{
	GSList *proxies;
	proxies = gtk_action_get_proxies (GTK_ACTION (action));
	if (proxies)
	{
		GaleonLocationEntry *gle = GALEON_LOCATION_ENTRY (GTK_BIN (proxies->data)->child);
		return galeon_location_entry_get_location (gle);
	}
	else
	{
		return g_strdup ("");
	}
}

void
galeon_action_location_set_location (GaleonActionLocation *action, const gchar *location)
{
	GSList *sli;
	for (sli = gtk_action_get_proxies (GTK_ACTION (action)); sli; sli = sli->next)
	{
		GaleonLocationEntry *gle = GALEON_LOCATION_ENTRY (GTK_BIN (sli->data)->child);
		return galeon_location_entry_set_location (gle, location);
	}
}

