/*
 *  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 GNgalU 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 <glib/gi18n.h>
#include "galeon-action.h"
#include "gul-gobject-misc.h"
#include "statusbar.h"

enum {
	PROP_0,
	PROP_WINDOW,
	PROP_EMBED
};

static void		galeon_action_init				(GaleonAction *action);
static void		galeon_action_class_init			(GaleonActionClass *class);
static void		galeon_action_finalize				(GObject *object);
static void		galeon_action_set_property			(GObject *object,
									 guint prop_id,
									 const GValue *value,
									 GParamSpec *pspec);
static void		galeon_action_get_property		 	(GObject *object,
									 guint prop_id,
									 GValue *value,
									 GParamSpec *pspec);
static void		galeon_action_current_embed_changed_impl	(GaleonAction *action, 
									 GaleonEmbed *old_embed,
									 GaleonEmbed *new_embed);
static void		galeon_action_update_impl			(GaleonAction *action);

static GtkActionClass *parent_class = NULL;

MAKE_GET_TYPE (galeon_action, "GaleonAction", GaleonAction, galeon_action_class_init, 
	       galeon_action_init, GTK_TYPE_ACTION);

static void
galeon_action_class_init (GaleonActionClass *class)
{
	GObjectClass *object_class = G_OBJECT_CLASS (class);

	object_class->finalize = galeon_action_finalize;
	object_class->set_property = galeon_action_set_property;
	object_class->get_property = galeon_action_get_property;

	class->update = galeon_action_update_impl;
	class->current_embed_changed = galeon_action_current_embed_changed_impl;

	g_object_class_install_property (object_class,
					 PROP_WINDOW,
					 g_param_spec_object ("window",
							      _("Window"),
							      _("The window associated with this action."),
							      GALEON_WINDOW_TYPE,
							      G_PARAM_READWRITE));

	parent_class = g_type_class_peek_parent (class);
}

static void
galeon_action_init (GaleonAction *action)
{
	
}

static void
galeon_action_finalize (GObject *object)
{
	GaleonAction *action = GALEON_ACTION(object);

	if (action->embed)
	{
		g_object_remove_weak_pointer(G_OBJECT(action->embed),
					     (gpointer *) &action->embed);
	}

	G_OBJECT_CLASS (parent_class)->finalize (object);
}

static void
galeon_action_set_property (GObject *object,
			    guint prop_id,
			    const GValue *value,
			    GParamSpec *pspec)
{
	GaleonAction *a = GALEON_ACTION (object);

	switch (prop_id)
	{
	case PROP_WINDOW:
		{
			GaleonWindow *w = g_value_get_object (value);
			galeon_action_set_window (a, w);
		}
		break;
	default: 
		break;
	}
}

static void
galeon_action_get_property (GObject *object,
			    guint prop_id,
			    GValue *value,
			    GParamSpec *pspec)
{
	GaleonAction *a = GALEON_ACTION (object);

	switch (prop_id)
	{
	case PROP_WINDOW:
		g_value_set_object (value, a->window);
		break;
	case PROP_EMBED:
		g_value_set_object (value, a->embed);
		break;
	default: 
		break;
	}
}

static void
galeon_action_update_active_embed (GaleonAction *action)
{
	GaleonEmbed *old_embed = action->embed;
	GaleonEmbed *new_embed;

	if (old_embed)
	{
		g_object_remove_weak_pointer(G_OBJECT(action->embed),
					     (gpointer *) &action->embed);
	}
	
	if (action->window)
	{
		new_embed = galeon_window_get_active_embed (action->window);
	}
	else 
	{
		new_embed = NULL;
	}

	action->embed = new_embed;

	if(action->embed)
	{
		g_object_add_weak_pointer(G_OBJECT(action->embed),
					  (gpointer *) &action->embed);
	}

	if (old_embed != new_embed)
	{
		galeon_action_current_embed_changed (action, old_embed, new_embed);
	}
}

static void 
galeon_action_active_embed_changed_cb (GaleonWindow *window, GaleonEmbed *old_embed, GaleonEmbed *new_embed,
				       GaleonAction *action)
{
	galeon_action_update_active_embed (action);
}

void
galeon_action_set_window (GaleonAction *action, GaleonWindow *window)
{
	if (action->window)
	{
		g_signal_handlers_disconnect_matched (action->window, G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, action);
	}
	action->window = window;
	if (action->window)
	{
		g_signal_connect_object (action->window, "active-embed-changed",
					 G_CALLBACK (galeon_action_active_embed_changed_cb),
					 action, 0);
	}

	galeon_action_update_active_embed (action);
}

GaleonWindow *
galeon_action_get_window (GaleonAction *action)
{
	return action->window;
}

GaleonEmbed *
galeon_action_get_embed (GaleonAction *action)
{
	return action->embed;
}

void
galeon_action_update (GaleonAction *action)
{
	GALEON_ACTION_GET_CLASS (action)->update (action);
}

void
galeon_action_current_embed_changed (GaleonAction *action, 
				     GaleonEmbed *old_embed, GaleonEmbed *new_embed)
{
	GALEON_ACTION_GET_CLASS (action)->current_embed_changed (action, old_embed, new_embed);
}

static void
galeon_action_current_embed_changed_impl (GaleonAction *action, 
					  GaleonEmbed *old_embed, GaleonEmbed *new_embed)
{
	/* empty default implementation */
}

static void
galeon_action_update_impl (GaleonAction *action)
{
	/* empty default implementation */
}
