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

/*
 *  Copyright (C) 2003-2004 Hiroyuki Ikezoe
 *  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-scrap-bookmark-action.h"

#include "kazehakase.h"
#include "kz-mozembed.h"
#include "kz-bookmark-menu.h"
#include "kz-bookmark-editor.h"
#include "intl.h"
#include "gobject-utils.h"
#include "egg-toolbutton.h"

#include <time.h>

enum {
	PROP_0,
	PROP_SCRAP_BOOKMARK,
	PROP_KZ_WINDOW,
};


static void kz_scrap_bookmark_action_class_init       (KzScrapBookmarkActionClass *class);
static void kz_scrap_bookmark_action_init             (KzScrapBookmarkAction      *action);
static void kz_scrap_bookmark_action_dispose          (GObject *obj);
static void kz_scrap_bookmark_action_set_property     (GObject           *object,
						       guint              prop_id,
						       const GValue      *value,
						       GParamSpec        *pspec);
static void kz_scrap_bookmark_action_get_property     (GObject           *object,
						       guint              prop_id,
						       GValue            *value,
						       GParamSpec        *pspec);

static void kz_scrap_bookmark_action_activate         (EggAction         *action);
static void kz_scrap_bookmark_action_connect_proxy    (EggAction         *action,
						       GtkWidget         *proxy);
static void kz_scrap_bookmark_action_disconnect_proxy (EggAction         *action,
						       GtkWidget         *proxy);


/* callbacks for child widgets */
static gboolean kz_scrap_bookmark_button_press_cb     (GtkWidget      *widget,
						       GdkEventButton *event,
						       KzScrapBookmarkAction   *action);
static void     kz_scrap_bookmark_menu_add_press_cb   (GtkWidget      *widget,
						       GdkEventButton *event,
						       KzScrapBookmarkAction   *action);
static void     kz_scrap_bookmark_menu_edit_press_cb  (GtkWidget      *widget,
						       GdkEventButton *event,
						       KzScrapBookmarkAction   *action);


static EggActionClass *parent_class = NULL;


KZ_OBJECT_GET_TYPE(kz_scrap_bookmark_action, "KzScrapBookmarkAction", KzScrapBookmarkAction,
		   kz_scrap_bookmark_action_class_init, kz_scrap_bookmark_action_init,
		   EGG_TYPE_ACTION)


static void
kz_scrap_bookmark_action_class_init (KzScrapBookmarkActionClass *klass)
{
	GObjectClass *object_class;
	EggActionClass *action_class;

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

	object_class->set_property     = kz_scrap_bookmark_action_set_property;
	object_class->get_property     = kz_scrap_bookmark_action_get_property;
	object_class->dispose          = kz_scrap_bookmark_action_dispose;

	action_class->activate         = kz_scrap_bookmark_action_activate;
	action_class->connect_proxy    = kz_scrap_bookmark_action_connect_proxy;
	action_class->disconnect_proxy = kz_scrap_bookmark_action_disconnect_proxy;

	g_object_class_install_property
		(object_class,
		 PROP_SCRAP_BOOKMARK,
		 g_param_spec_object ("scrap_bookmark",
				      _("ScrapBookmark Object"),
				      _("ScrapBookmark object"),
				      KZ_TYPE_BOOKMARK,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));

	g_object_class_install_property
		(object_class,
		 PROP_KZ_WINDOW,
		 g_param_spec_object ("kz-window",
				      _("KzWindow"),
				      _("The KzWindow to add a scrap_bookmark button"),
				      KZ_TYPE_WINDOW,
				      G_PARAM_READWRITE |
				      G_PARAM_CONSTRUCT_ONLY));
}


static void
kz_scrap_bookmark_action_init (KzScrapBookmarkAction *action)
{
	action->popup_menu = NULL;
	action->scrap      = NULL;
	action->kz         = NULL;
}


static void
kz_scrap_bookmark_action_dispose (GObject *obj)
{
	KzScrapBookmarkAction *action = KZ_SCRAP_BOOKMARK_ACTION(obj);

	if (action->scrap)
		g_object_unref(action->scrap);
	action->scrap = NULL;

	if (action->kz)
		g_object_unref(action->kz);
	action->kz = NULL;

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


static void
kz_scrap_bookmark_action_set_property (GObject         *object,
				       guint            prop_id,
				       const GValue    *value,
				       GParamSpec      *pspec)
{
	KzScrapBookmarkAction *action = KZ_SCRAP_BOOKMARK_ACTION(object);
  
	switch (prop_id)
	{
	case PROP_SCRAP_BOOKMARK:
		action->scrap = g_object_ref(g_value_get_object(value));
		break;
	case PROP_KZ_WINDOW:
		action->kz = g_object_ref(g_value_get_object(value));
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


static void
kz_scrap_bookmark_action_get_property (GObject         *object,
				       guint            prop_id,
				       GValue          *value,
				       GParamSpec      *pspec)
{
	KzScrapBookmarkAction *action = KZ_SCRAP_BOOKMARK_ACTION(object);

	switch (prop_id)
	{
	case PROP_SCRAP_BOOKMARK:
		g_value_set_object(value, action->scrap);
		break;
	case PROP_KZ_WINDOW:
		g_value_set_object(value, action->kz);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}


KzScrapBookmarkAction *
kz_scrap_bookmark_action_new(KzBookmark *scrap_bookmark, KzWindow *kz)
{
	KzScrapBookmarkAction *action;

	action = KZ_SCRAP_BOOKMARK_ACTION(g_object_new(KZ_TYPE_SCRAP_BOOKMARK_ACTION,
						       "name",      "ScrapBookmark",
						       "label",     _("_ScrapBookmark"),
						       "tooltip",   NULL,
						       "stock_id",  KZ_STOCK_BOOKMARK,
						       "scrap_bookmark",      scrap_bookmark,
						       "kz-window", kz,
						       NULL));

	return action;
}


static void
kz_scrap_bookmark_action_activate (EggAction *action)
{
	KzBookmark *scrap;
	KzWindow *kz;
	const gchar *uri;

	scrap = KZ_SCRAP_BOOKMARK_ACTION(action)->scrap;
	g_return_if_fail(KZ_IS_BOOKMARK(scrap));

	kz = KZ_SCRAP_BOOKMARK_ACTION(action)->kz;
	if (!KZ_IS_WINDOW(kz)) return;

	uri = kz_bookmark_get_link(scrap);

	kz_window_load_url(kz, uri);
}


static void
kz_scrap_bookmark_action_connect_proxy (EggAction *action, GtkWidget *proxy)
{
	GtkWidget *real_proxy = NULL;

	EGG_ACTION_CLASS (parent_class)->connect_proxy (action, proxy);

	if (GTK_IS_MENU_ITEM(proxy) || GTK_IS_BUTTON(proxy))
		real_proxy = proxy;
	else if (EGG_IS_TOOL_BUTTON(proxy))
		real_proxy = EGG_TOOL_BUTTON(proxy)->button;

	if (real_proxy)
	{
		g_signal_connect(G_OBJECT(real_proxy),
				 "button_press_event",
				 G_CALLBACK(kz_scrap_bookmark_button_press_cb),
				 action);
	}
}


static void
kz_scrap_bookmark_action_disconnect_proxy (EggAction *action, GtkWidget *proxy)
{
	GtkWidget *real_proxy = NULL;

	EGG_ACTION_CLASS (parent_class)->disconnect_proxy (action, proxy);

	if (GTK_IS_MENU_ITEM(proxy) || GTK_IS_BUTTON(proxy))
		real_proxy = proxy;
	else if (EGG_IS_TOOL_BUTTON(proxy))
		real_proxy = EGG_TOOL_BUTTON(proxy)->button;

	if (real_proxy)
	{
		g_signal_handlers_disconnect_by_func
			(G_OBJECT(real_proxy),
			 G_CALLBACK(kz_scrap_bookmark_button_press_cb),
			 action);
	}
}


/* create lairs menu */
static GtkWidget *
kz_scrap_bookmark_menu_new (KzScrapBookmarkAction *action)
{
	GtkWidget *menu, *menu_item;
	
	menu = gtk_menu_new();
	g_object_ref(G_OBJECT(menu));
	gtk_object_sink(GTK_OBJECT(menu));

	/* Add lairs */
	menu_item = gtk_menu_item_new_with_mnemonic(_("_Add to Scrap Bookmark"));
	gtk_menu_shell_append(GTK_MENU_SHELL(menu),
			      menu_item);
	g_signal_connect(G_OBJECT(menu_item), "button_press_event",
			 G_CALLBACK(kz_scrap_bookmark_menu_add_press_cb),
			 action);
	gtk_widget_show(menu_item);

	/* Edit */
	menu_item = gtk_menu_item_new_with_mnemonic(_("_Edit Scrap Bookmark"));
	gtk_menu_shell_append(GTK_MENU_SHELL(menu),
			      menu_item);
	g_signal_connect(G_OBJECT(menu_item), "button_press_event",
			 G_CALLBACK(kz_scrap_bookmark_menu_edit_press_cb),
			 action);
	gtk_widget_show(menu_item);

	/* separator */
	menu_item = gtk_separator_menu_item_new();
	gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
	gtk_widget_show(menu_item);

	/* children */
	kz_bookmark_menu_remove_menuitems(GTK_MENU_SHELL(menu),
					  action->kz);
	kz_bookmark_menu_append_menuitems(GTK_MENU_SHELL(menu),
					  action->kz, action->scrap);
	gtk_widget_show(menu);

	return menu;
}


static gboolean
kz_scrap_bookmark_button_press_cb (GtkWidget *widget,
				   GdkEventButton *event,
				   KzScrapBookmarkAction *action)
{
	KzBookmark *scrap = action->scrap;
	KzWindow *kz = action->kz;
	const gchar *uri = kz_bookmark_get_link(scrap);

	if (!KZ_IS_WINDOW(kz)) return FALSE;

	if (action->popup_menu != NULL)
	{	
		g_object_unref(G_OBJECT(action->popup_menu));
	}
	action->popup_menu = kz_scrap_bookmark_menu_new(action);

	switch (event->button)
	{
	case 2: /* open in new tab */
		kz_window_open_new_tab(kz, uri);

		return TRUE;
		break;
	case 3: /* popup secret menu */
		gtk_menu_popup(GTK_MENU(action->popup_menu),
			       NULL, NULL, NULL, NULL,
			       event->button, event->time);
		return TRUE;
		break;
	}

	return FALSE;
}


static void
kz_scrap_bookmark_menu_add_press_cb (GtkWidget *widget,
				     GdkEventButton *event,
				     KzScrapBookmarkAction *action)
{
	KzBookmark *scrap = action->scrap, *child;
	KzWindow *kz = action->kz;
	GtkWidget *embed;
	const gchar *title, *uri;
	gchar *desc = NULL;
	GTimeVal now;
	struct tm *date = NULL;
	time_t t;
	gchar link_string[20];
	gchar *link;

	if (!KZ_IS_WINDOW(kz)) return;

	embed = KZ_WINDOW_CURRENT_PAGE(kz);
	if (!KZ_IS_MOZ_EMBED(embed)) return;

	g_get_current_time(&now);

	title = kz_window_get_title(kz);
	uri   = kz_window_get_uri(kz);
	desc  = kz_moz_embed_get_selection_source(KZ_MOZ_EMBED(embed));

	child = kz_bookmark_new_with_attrs(title, uri, desc);
	kz_bookmark_set_location(child, uri);

	kz_bookmark_set_last_modified(child, now.tv_sec);
	
	t = (time_t)now.tv_sec;
	date = localtime(&t);

	/* link */
	strftime(link_string, 20, "#%Y%m%d%H%M%S", date);
	link = g_strdup_printf("file://%s%s",
			       kz_bookmark_get_location(scrap),
			       link_string);
	kz_bookmark_set_link(child, link);


	kz_bookmark_prepend(scrap, child);
	g_object_unref(child);

	if (desc)
		g_free(desc);
	/* save scrap.html */
	kz_bookmark_save(scrap);
}


static void
kz_scrap_bookmark_menu_edit_press_cb (GtkWidget *widget,
				      GdkEventButton *event,
				      KzScrapBookmarkAction *action)
{
	KzBookmark *scrap = action->scrap;
	GtkWidget *editor;

	editor = kz_bookmark_editor_new(scrap);
	gtk_widget_show(editor);
}
