/*
 *  Copyright (C) 2002  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 "bookmarks-tb-widget.h"
#include "bookmarks-context-menu.h"
#include "galeon-marshal.h"
#include "galeon-debug.h"
#include "gul-gobject-misc.h"

#include <glib/gi18n.h>

/**
 * Private data
 */
struct _GbTbWidgetPrivate {
	GbBookmark *bm;
	GbLocationSource *location_source;
};

/**
 * Private functions, only availble from this file
 */
static void		gb_tb_widget_class_init		(GbTbWidgetClass *klass);
static void		gb_tb_widget_init		(GbTbWidget *w);
static void		gb_tb_widget_finalize_impl 	(GObject *o);

static void		gb_tb_widget_modified_cb	(GbBookmark *b, GbTbWidget *w);
static gboolean		gb_tb_widget_popup_menu_cb	(GtkWidget *b, GbTbWidget *w);
static gboolean 	gb_tb_widget_button_press_cb 	(GtkWidget *wid, GdkEventButton *event, 
							 GbTbWidget *w);
static void		gb_tb_widget_rebuild_impl	(GbTbWidget *w);
static void		gb_tb_widget_set_property_impl	(GObject *object,
							 guint prop_id,
							 const GValue *value,
							 GParamSpec *pspec);
static void		gb_tb_widget_get_property_impl	(GObject *object,
							 guint prop_id,
							 GValue *value,
							 GParamSpec *pspec);

static gpointer gtk_hbox_class;

/* signals enums and ids */
enum GbTbWidgetSignalsEnum {
	GB_TB_WIDGET_BOOKMARK_ACTIVATED,
	GB_TB_WIDGET_LAST_SIGNAL
};
static gint GbTbWidgetSignals[GB_TB_WIDGET_LAST_SIGNAL];

/* properties */
enum {
  PROP_0,
  PROP_BOOKMARK
};

/**
 * GbTbWidget object
 */

MAKE_GET_TYPE (gb_tb_widget, "GbTbWidget", GbTbWidget, gb_tb_widget_class_init, 
	       gb_tb_widget_init, GTK_TYPE_HBOX);

static void
gb_tb_widget_class_init (GbTbWidgetClass *klass)
{
	G_OBJECT_CLASS (klass)->finalize = gb_tb_widget_finalize_impl;
	G_OBJECT_CLASS (klass)->set_property = gb_tb_widget_set_property_impl;
	G_OBJECT_CLASS (klass)->get_property = gb_tb_widget_get_property_impl;
	klass->rebuild = gb_tb_widget_rebuild_impl;
	gtk_hbox_class = g_type_class_peek_parent (klass);

	GbTbWidgetSignals[GB_TB_WIDGET_BOOKMARK_ACTIVATED] = g_signal_new (
		"bookmark-activated", G_OBJECT_CLASS_TYPE (klass),  
		G_SIGNAL_RUN_FIRST | G_SIGNAL_RUN_LAST | G_SIGNAL_RUN_CLEANUP,
                G_STRUCT_OFFSET (GbTbWidgetClass, gb_tb_widget_bookmark_activated), 
		NULL, NULL, 
		g_cclosure_marshal_VOID__POINTER,
		G_TYPE_NONE, 1, G_TYPE_POINTER);
	
	g_object_class_install_property (G_OBJECT_CLASS (klass),
					 PROP_BOOKMARK,
					 g_param_spec_object ("bookmark",
							      _("Bookmark"),
							      _("Bookmark represented."),
							      GB_TYPE_BOOKMARK,
							      G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));

}

static void 
gb_tb_widget_init (GbTbWidget *w)
{
	GbTbWidgetPrivate *p = g_new0 (GbTbWidgetPrivate, 1);
	w->priv = p;
}

static void
gb_tb_widget_finalize_impl (GObject *o)
{
	GbTbWidget *w = GB_TB_WIDGET (o);
	GbTbWidgetPrivate *p = w->priv;

	gb_tb_widget_set_location_source (w, NULL);

	if (p->bm)
	{
		g_signal_handlers_disconnect_matched (p->bm, G_SIGNAL_MATCH_DATA, 0, 0, 
						      NULL, NULL, w);
		g_object_unref (G_OBJECT (p->bm));

	}

	g_free (p);

	LOG ("GbTbWidget finalized");

	G_OBJECT_CLASS (gtk_hbox_class)->finalize (o);
}

void
gb_tb_widget_rebuild (GbTbWidget *w)
{
	GbTbWidgetClass *klass = GB_TB_WIDGET_GET_CLASS (w);
	klass->rebuild (w);
}

static void
gb_tb_widget_modified_cb (GbBookmark *b, GbTbWidget *w)
{
	gb_tb_widget_rebuild (w);
}

static gboolean
gb_tb_widget_popup_menu_cb (GtkWidget *b, GbTbWidget *w)
{
	GbTbWidgetPrivate *p = w->priv;
	gb_context_menu_quick (p->bm, NULL, p->location_source, G_OBJECT (w));
	return TRUE;
}

static gboolean
gb_tb_widget_button_press_cb (GtkWidget *wid, GdkEventButton *event, 
			      GbTbWidget *w)
{
	GbTbWidgetPrivate *p = w->priv;
	g_return_val_if_fail (GB_IS_BOOKMARK (p->bm), FALSE);

	if (event->button == 3)
	{
		gb_context_menu_quick (p->bm, event, p->location_source, G_OBJECT (w));
		return TRUE;
	}
	else if (event->button == 2)
	{
		const gchar *url = GB_IS_SITE (p->bm) ? GB_SITE (p->bm)->url : NULL;
		gb_activated_event (w, p->bm, url, GB_BAF_NEW_TAB_OR_WINDOW, (GdkEvent *) event);
		return TRUE;
	}
	return FALSE;
}

GbBookmark *
gb_tb_widget_get_bookmark (GbTbWidget *gtw)
{
	return gtw->priv->bm;
}

static void
gb_tb_widget_set_property_impl (GObject *object,
				guint prop_id,
				const GValue *value,
				GParamSpec *pspec)
{
	GbTbWidget *tbw = GB_TB_WIDGET (object);
	GbTbWidgetPrivate *p = tbw->priv;

	switch (prop_id)
	{
	case PROP_BOOKMARK:
		g_return_if_fail (p->bm == NULL);
		p->bm = g_value_get_object (value);
		g_object_ref (p->bm);
		g_signal_connect (p->bm, "modified", G_CALLBACK (gb_tb_widget_modified_cb), tbw);
		gb_tb_widget_rebuild (tbw);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

static void
gb_tb_widget_get_property_impl (GObject *object,
				guint prop_id,
				GValue *value,
				GParamSpec *pspec)
{
	GbTbWidget *tbw = GB_TB_WIDGET (object);
	GbTbWidgetPrivate *p = tbw->priv;

	switch (prop_id)
	{
	case PROP_BOOKMARK:
		g_value_set_object (value, p->bm);
		break;
	default:
		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
		break;
	}
}

void
gb_tb_widget_setup_context_menu	(GbTbWidget *gtw, GtkWidget *w)
{
	g_signal_connect (w, "popup_menu", 
			  G_CALLBACK (gb_tb_widget_popup_menu_cb), gtw);
	g_signal_connect (w, "button_press_event",
			  G_CALLBACK (gb_tb_widget_button_press_cb), gtw);
}

static void
gb_tb_widget_rebuild_impl (GbTbWidget *w)
{
	g_warning ("Should not be reached");
}

void
gb_tb_widget_set_location_source (GbTbWidget *w, GbLocationSource *src)
{
	GbTbWidgetPrivate *p = w->priv;

	if (p->location_source)
	{
		g_object_remove_weak_pointer (G_OBJECT (p->location_source),
					      (gpointer *) &p->location_source);
	}

	p->location_source = src;

	if (p->location_source)
	{
		g_object_add_weak_pointer (G_OBJECT (p->location_source), 
					   (gpointer *) &p->location_source);
	}
}


GbLocationSource *
gb_tb_widget_get_location_source (GbTbWidget *w)
{
	GbTbWidgetPrivate *p = w->priv;
	return p->location_source;
}

