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

/*
 *  Copyright (C) 2003 Takuro Ashie
 *
 *  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-actions-tab.h"

#include <string.h>
#include <glib/gi18n.h>
#include "gtk-utils.h"
#include "kazehakase.h"
#include "kz-icons.h"

static GQuark kztab_quark = 0;


static void
act_tab_reload (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	kz_embed_reload(kztab->kzembed,
			KZ_EMBED_RELOAD_NORMAL);
}

static void
act_tab_stop (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	kz_embed_stop_load(kztab->kzembed);
}

static void
act_tab_close (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	kz_window_close_tab(kztab->kz, GTK_WIDGET(kztab->kzembed));
}

static void
close_all_tab (GtkAction *action, KzWindow *kz, gint mode)
{
	KzTabLabel *kztab;
	GtkNotebook *notebook;
	gint num, pos;
	gint i;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);

	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
	notebook = GTK_NOTEBOOK(kztab->kz->notebook);

	num = gtk_notebook_get_n_pages(notebook);
	pos = gtk_notebook_page_num(notebook, GTK_WIDGET(kztab->kzembed));

	if (num < 2 || pos < 0) return;

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kztab->kz, i);

		if (i == pos) continue;
		if (i > pos && mode == 1) continue;
		if (i < pos && mode == 2) continue;

		kz_window_close_tab(kztab->kz, widget);
	}
}

static void
act_tab_close_left (GtkAction *action, KzWindow *kz)
{
	close_all_tab(action, kz, 1);
}

static void
act_tab_close_right (GtkAction *action, KzWindow *kz)
{
	close_all_tab(action, kz, 2);
}

static void
act_tab_close_all_without_active (GtkAction *action, KzWindow *kz)
{
	close_all_tab(action, kz, 0);
}


static gboolean
get_all_under_current_tab (GNode *node, gpointer data)
{
	GList **list = data;

	*list = g_list_append(*list, node->data);

	return FALSE;
}


static void
act_tab_close_all_child (GtkAction *action, KzWindow *kz)
{
	KzEmbed *kzembed;
	KzTabLabel *kztab;
	GNode *tree, *parent;
	GList *list = NULL, *node;

	g_return_if_fail(KZ_IS_WINDOW (kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);

	kzembed = kztab->kzembed;
	tree = kz_window_get_tree(kz);
	parent = g_node_find(tree, G_IN_ORDER, G_TRAVERSE_ALL, kzembed);
	g_return_if_fail(parent);

	g_node_traverse(parent, G_PRE_ORDER, G_TRAVERSE_ALL, -1,
			get_all_under_current_tab, &list);
	for (node = list; node; node = g_list_next(node))
	{
		GtkWidget *widget = node->data;

		if (widget != GTK_WIDGET(kzembed))
			kz_window_close_tab(kz, widget);
	}
	g_list_free(list);
}


static void
act_tab_copy_title (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	gtkutil_copy_text(kz_embed_get_title(KZ_EMBED(kztab->kzembed)));
}

static void
act_tab_copy_location (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	gtkutil_copy_text(kz_embed_get_location(KZ_EMBED(kztab->kzembed)));
}

static void
act_tab_copy_title_and_location (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;
	gchar *str;

	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	str = g_strdup_printf("<a href=\"%s\" title=\"%s\">%s</a>",
			      kz_embed_get_location(KZ_EMBED(kztab->kzembed)),
			      kz_embed_get_title(KZ_EMBED(kztab->kzembed)),
			      kz_embed_get_title(KZ_EMBED(kztab->kzembed)));
	gtkutil_copy_text(str);
	g_free(str);
}

static void
act_tab_toggle_lock (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(GTK_IS_TOGGLE_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)))
		kz_tab_label_set_lock(kztab, TRUE);
	else
		kz_tab_label_set_lock(kztab, FALSE);
}

static void
act_tab_toggle_auto_refresh (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;

	g_return_if_fail(GTK_IS_TOGGLE_ACTION(action));
	g_return_if_fail(KZ_IS_WINDOW(kz));

	kztab = g_object_get_qdata(G_OBJECT(kz), kztab_quark);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	if (gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action)))
		kz_tab_label_set_auto_refresh(kztab, TRUE);
	else
		kz_tab_label_set_auto_refresh(kztab, FALSE);
}

static void
act_tab_copy_tab (GtkAction *action, KzWindow *kz)
{
	GtkWidget *widget = KZ_WINDOW_CURRENT_PAGE(kz);
	KzEmbed *kzembed, *dkzembed;

	g_return_if_fail(KZ_IS_WINDOW(kz));
	g_return_if_fail(KZ_EMBED(widget));
	
	kzembed  = KZ_EMBED(widget);	
	dkzembed = KZ_EMBED(kz_window_open_new_tab(kz, NULL));

	kz_embed_copy_page(kzembed, dkzembed);
	kz_embed_shistory_copy(kzembed, dkzembed, TRUE, TRUE, TRUE);
}

GtkActionEntry kz_actions_tab[] =
{
        /* Toplevel */
	{"TabReload", GTK_STOCK_REFRESH, N_("Reloa_d"),
	 NULL, NULL, G_CALLBACK(act_tab_reload)},

	{"TabStop",  GTK_STOCK_STOP, N_("_Stop"),
	 NULL, NULL, G_CALLBACK(act_tab_stop)},

	{"TabClose", GTK_STOCK_CLOSE, N_("_Close"),
	 NULL, NULL, G_CALLBACK(act_tab_close)},

	{"TabCloseAllBackward", KZ_STOCK_CLOSE_BACKWARD , N_("Close all _backward tabs"),
	 NULL, NULL, G_CALLBACK(act_tab_close_left)},

	{"TabCloseAllForward", KZ_STOCK_CLOSE_FORWARD, N_("Close all _forward tabs"), 
	 NULL, NULL, G_CALLBACK(act_tab_close_right)},

	{"TabCloseAllWithoutActive", GTK_STOCK_CLOSE, N_("Close all with_out this tab"),
	 NULL, NULL, G_CALLBACK(act_tab_close_all_without_active)},

	{"TabCloseAllChild", GTK_STOCK_CLOSE, N_("Close all c_hild tab"),
	 NULL, NULL, G_CALLBACK(act_tab_close_all_child)},

	{"TabCopyTitle",        NULL, N_("Copy _Title"),
	 NULL, NULL, G_CALLBACK(act_tab_copy_title)},

	{"TabCopyLocation", KZ_STOCK_COPY_URL, N_("Copy _Location"),
	 NULL, NULL, G_CALLBACK(act_tab_copy_location)},

	{"TabCopyTitleLocation",     NULL, N_("Cop_y Title&Location"),
	 NULL, NULL, G_CALLBACK(act_tab_copy_title_and_location)},

	{"TabCopy",     NULL, N_("Tab Co_py"),
	 NULL, NULL, G_CALLBACK(act_tab_copy_tab)},
};


GtkToggleActionEntry kz_toggle_actions_tab[] =
{
	{"TabToggleLock",     KZ_STOCK_ANCHOR, N_("Tab Loc_k"),
	 NULL, NULL, G_CALLBACK(act_tab_toggle_lock), FALSE},
	{"TabAutoRefresh",     KZ_STOCK_ANCHOR, N_("Refresh Tab _automatically"),
	 NULL, NULL, G_CALLBACK(act_tab_toggle_auto_refresh), FALSE},
};
const gint kz_actions_tab_len = G_N_ELEMENTS(kz_actions_tab);
const gint kz_toggle_actions_tab_len = G_N_ELEMENTS(kz_toggle_actions_tab);


GtkActionGroup *
kz_actions_tab_popup_create_group (KzWindow *kz, GtkAccelGroup *accel_group)
{
	GtkActionGroup *action_group;
	GList *node, *action_list;

	action_group = gtk_action_group_new("KzWindowTabPopup");

	gtk_action_group_set_translation_domain(action_group, NULL);

	gtk_action_group_add_actions (action_group,
				      kz_actions_tab,
				      kz_actions_tab_len,
				      kz);

	gtk_action_group_add_toggle_actions(action_group,
					    kz_toggle_actions_tab,
					    kz_toggle_actions_tab_len,
					    kz);
	
	action_list = gtk_action_group_list_actions(action_group);
	
	for (node = action_list; node; node = g_list_next(node))
	{
		gtk_action_set_accel_group(GTK_ACTION(node->data),
					   accel_group);
		gtk_action_connect_accelerator(GTK_ACTION(node->data));
	}
	g_list_free(action_list);

	return action_group;
}


static void
cb_popup_menu_hide (void)
{
	gtk_main_quit();
}


static void
set_popup_menu_sensitive (KzTabLabel *kztab)
{
	KzWindow *kz;
	GtkAction *action;
	gint pos, num;
	gboolean lock, auto_refresh;

	g_return_if_fail(kztab);

	kz = kztab->kz;
	g_return_if_fail(KZ_IS_WINDOW(kz));

	pos = gtk_notebook_page_num(GTK_NOTEBOOK(kztab->kz->notebook),
				    GTK_WIDGET(kztab->kzembed));
	num = gtk_notebook_get_n_pages(GTK_NOTEBOOK(kztab->kz->notebook));

	action = gtk_action_group_get_action(kz->tabpop_actions, "TabStop");
	g_object_set(action, "sensitive", 
		     kz_embed_is_loading(kztab->kzembed),
		     NULL);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabCloseAllBackward");
	g_object_set(action, "sensitive", !(pos == 0), NULL);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabCloseAllForward");
	g_object_set(action, "sensitive", !(pos == num -1), NULL);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabCloseAllWithoutActive");
	g_object_set(action, "sensitive", num > 1, NULL);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabToggleLock");
	lock = kz_tab_label_get_lock(kztab);
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), lock);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabAutoRefresh");
	auto_refresh = kz_tab_label_get_auto_refresh(kztab);
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), auto_refresh);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabClose");
	g_object_set(action, "sensitive", !lock, NULL);
}


void
kz_actions_tab_popup_menu_modal (KzTabLabel *kztab, guint button, guint time)
{
	GtkWidget *popup_menu = NULL;
	gchar path[64];

	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
	g_return_if_fail(KZ_IS_WINDOW(kztab->kz));

	if (!kztab_quark)
		kztab_quark = g_quark_from_string("KzTabAction::KzTabLabelFor");

	g_object_set_qdata(G_OBJECT(kztab->kz), kztab_quark, kztab);

	g_snprintf(path, sizeof(path), "/TabPopup%s",
		   kz_ui_level_to_suffix(kz_ui_level()));
	popup_menu = gtk_ui_manager_get_widget(kztab->kz->menu_merge, path);
	if (!popup_menu) return;

	set_popup_menu_sensitive(kztab);

	g_signal_connect(G_OBJECT(popup_menu), "hide",
			 G_CALLBACK(cb_popup_menu_hide), NULL);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, button, time);
	gtk_main();
	g_signal_handlers_disconnect_by_func(G_OBJECT(popup_menu),
					     G_CALLBACK(cb_popup_menu_hide),
					     NULL);

	g_object_set_qdata(G_OBJECT(kztab->kz), kztab_quark, NULL);
}


void
kz_actions_tab_activate_action (KzTabLabel *kztab, GtkAction *action)
{
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));
	g_return_if_fail(KZ_IS_WINDOW(kztab->kz));

	if (!kztab_quark)
		kztab_quark = g_quark_from_string("KzTabAction::KzTabLabelFor");

	g_object_set_qdata(G_OBJECT(kztab->kz), kztab_quark, kztab);

	gtk_action_activate(action);

	g_object_set_qdata(G_OBJECT(kztab->kz), kztab_quark, NULL);
}
