/* -*- 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"
#include "kz-notebook.h"
#include "kz-actions-dynamic.h"

static GQuark kztab_quark = 0;


static KzTabLabel *
get_tab_object (KzWindow *kz)
{
	KzTabLabel *kztab;

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

	if (!kztab)
	{
		GtkWidget *label;
		GtkWidget *kzembed;

		kzembed = GTK_WIDGET(KZ_WINDOW_CURRENT_PAGE(kz));
		label = gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
						   kzembed);
		if (KZ_IS_TAB_LABEL(label))
			kztab = KZ_TAB_LABEL(label);
	}

	return kztab;
}

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));
}

enum {
	KZ_TAB_CLOSE_ALL_TABS = -1,
	KZ_TAB_CLOSE_INACTIVE,
	KZ_TAB_CLOSE_BACKWARD,
	KZ_TAB_CLOSE_FORWARD
};

static void
close_tabs (KzWindow *kz, KzNotebookCloseCondition condition)
{
	KzTabLabel *kztab;
	GtkNotebook *notebook;
	gint pos;

	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);

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

	kz_notebook_close_tabs(KZ_NOTEBOOK(notebook), condition, pos);
}

static void
act_tab_close_left (GtkAction *action, KzWindow *kz)
{
	close_tabs(kz, KZ_NOTEBOOK_CLOSE_BACKWARD);
}

static void
act_tab_close_right (GtkAction *action, KzWindow *kz)
{
	close_tabs(kz, KZ_NOTEBOOK_CLOSE_FORWARD);
}

static void
act_tab_close_all_inactive (GtkAction *action, KzWindow *kz)
{
	close_tabs(kz, KZ_NOTEBOOK_CLOSE_INACTIVE);
}

static void
act_tab_close_all_tabs (GtkAction *action, KzWindow *kz)
{
	g_return_if_fail(KZ_IS_WINDOW(kz));
	kz_window_close_all_tab(kz);
}

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_close_all_same_site (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;
	GtkNotebook *notebook;
	gint num;
	gint i;
	gchar **src;
	gchar **target;

	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);
	if (num < 2) return;

	src = g_strsplit(kz_embed_get_location(KZ_EMBED(kztab->kzembed)),
			"/", 0);

	for (i = num - 1; i >= 0; i--)
	{
		GtkWidget *widget = KZ_WINDOW_NTH_PAGE(kz, i);
		kztab = KZ_TAB_LABEL(gtk_notebook_get_tab_label(GTK_NOTEBOOK(kz->notebook),
							widget));
		target = g_strsplit(kz_embed_get_location(KZ_EMBED(kztab->kzembed)),
				"/", 0);

		if(!(strcmp(src[2] , target[2])))
		{
			kz_window_close_tab(kz, widget);
		}
		g_strfreev(target);
	}
	g_strfreev(src);
}

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 = get_tab_object(kz);
	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;
	gboolean active;

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

	kztab = get_tab_object(kz);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	kz_tab_label_set_lock(kztab, active);
}

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

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

	kztab = get_tab_object(kz);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));
	kz_tab_label_set_auto_refresh(kztab, active);
}

static void
act_tab_toggle_javascript (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;
	gboolean active;

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

	kztab = get_tab_object(kz);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));

	kz_embed_set_allow_javascript(KZ_EMBED(kztab->kzembed), active);
	kz_tab_label_set_javascript(kztab, active);
}

static void
act_tab_toggle_images (GtkAction *action, KzWindow *kz)
{
	KzTabLabel *kztab;
	gboolean active;

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

	kztab = get_tab_object(kz);
	g_return_if_fail(KZ_IS_TAB_LABEL(kztab));

	active = gtk_toggle_action_get_active (GTK_TOGGLE_ACTION(action));

	kz_embed_set_allow_images(KZ_EMBED(kztab->kzembed), active);
}

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_COPY_NORMAL);
	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)},

	{"TabAddFeedBookmark", NULL, N_("Add _feed to bookmarks"),
	 NULL,  NULL, NULL},
	
	{"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)},

	{"TabCloseAllInactiveTabs", GTK_STOCK_CLOSE, N_("Close all _inactive tabs"),
	 NULL, NULL, G_CALLBACK(act_tab_close_all_inactive)},

	{"TabCloseAllTabs", GTK_STOCK_CLOSE, N_("Clos_e all tabs"),
	 NULL, NULL, G_CALLBACK(act_tab_close_all_tabs)},

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

	{"TabCloseAllSameSiteAsThis", GTK_STOCK_CLOSE, N_("Close all tabs which _open the same site as this"),
	 NULL, NULL, G_CALLBACK(act_tab_close_all_same_site)},

	{"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",     NULL,           N_("Refresh Tab _automatically"),
	 NULL, NULL, G_CALLBACK(act_tab_toggle_auto_refresh), FALSE},
	{"TabToggleJavascript",NULL,           N_("Enable _javascript"),
	 NULL, NULL, G_CALLBACK(act_tab_toggle_javascript),   FALSE},
	{"TabToggleImages",NULL,               N_("Show _images"),
	 NULL, NULL, G_CALLBACK(act_tab_toggle_images),   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)
{
	GtkActionGroup *action_group;

	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);

	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, javascript, images, has_feed;

	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,
					     "TabAddFeedBookmark");
	if (kztab->kzembed &&
	    kz_embed_get_nav_link(kztab->kzembed, KZ_EMBED_LINK_RSS))
		has_feed = TRUE;
	else
		has_feed = FALSE;
	g_object_set(action, "sensitive", has_feed, 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,
					     "TabCloseAllInactiveTabs");
	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,
					     "TabToggleJavascript");
	javascript = kz_embed_get_allow_javascript(KZ_EMBED(kztab->kzembed));
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), javascript);

	action = gtk_action_group_get_action(kz->tabpop_actions,
					     "TabToggleImages");
	images = kz_embed_get_allow_images(KZ_EMBED(kztab->kzembed));
	gtk_toggle_action_set_active(GTK_TOGGLE_ACTION(action), images);

	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;
	GtkWidget *extra_menu = NULL;
	
	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);

	popup_menu = gtk_ui_manager_get_widget(kztab->kz->menu_merge, 
					       "/TabPopup");
	if (!popup_menu) return;

        /* add copy in user format */
	extra_menu = gtk_ui_manager_get_widget(kztab->kz->menu_merge,
					       "/TabPopup/CopyInUserFormat");
	if(extra_menu)
	{
		kz_actions_dynamic_append_copy_in_user_format_menuitem
			(kztab, GTK_MENU_ITEM(extra_menu));
	}

	/* add available feeds */
	extra_menu = gtk_ui_manager_get_widget(kztab->kz->menu_merge,
					       "/TabPopup/TabAddFeedBookmark");
	if (extra_menu)
	{
		kz_actions_dynamic_append_add_feed_bookmark
			(kztab->kz, GTK_MENU_ITEM(extra_menu));
	}

	set_popup_menu_sensitive(kztab);

	g_signal_connect(popup_menu, "hide",
			 G_CALLBACK(cb_popup_menu_hide), NULL);
	gtk_menu_popup(GTK_MENU(popup_menu), NULL, NULL,
		       NULL, NULL, 0, time);
	gtk_main();
	g_signal_handlers_disconnect_by_func(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);
}
