/*
 *  Copyright (C) 2002 Marco Pesenti Gritti
 *  Copyright (C) 2003 Philip Langdale (Egg port)
 *
 *  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 "ppview-toolbar.h"
#include "galeon-window.h"
#include "gul-string.h"
#include "gul-gui.h"
#include "galeon-debug.h"

#include <string.h>
#include <glib/gi18n.h>
#include <gtk/gtkentry.h>
#include <gtk/gtkmenu.h>
#include <gtk/gtkaction.h>
#include <gtk/gtkactiongroup.h>
#include "egg-dock.h"

#define ACTION_ITEM(name) gtk_action_group_get_action(t->priv->action_group, name)

#define PPV_GOTO_FIRST_ACTION "PPVGotoFirstAction"
#define PPV_GOTO_LAST_ACTION "PPVGotoLastAction"
#define PPV_GO_BACK_ACTION "PPVGoBackAction"
#define PPV_GO_FORWARD_ACTION "PPVGoForwardAction"
#define PPV_PRINT_ACTION "PPVPrintAction"


static void ppview_toolbar_class_init(PPViewToolbarClass *klass);
static void ppview_toolbar_init(PPViewToolbar *t);
static void ppview_toolbar_finalize(GObject *object);
static void ppview_toolbar_set_window(PPViewToolbar *t, GaleonWindow *window);
static void
ppview_toolbar_set_property(GObject *object,
                            guint prop_id,
                            const GValue *value,
                            GParamSpec *pspec);
static void
ppview_toolbar_get_property(GObject *object,
                            guint prop_id,
                            GValue *value,
                            GParamSpec *pspec);

enum
{
	PROP_0,
	PROP_GALEON_WINDOW,
	PROP_DOCK_ITEM
};

enum
{
	PRINT,
	LAST_SIGNAL
};

static guint signals[LAST_SIGNAL] = { 0 };

static GObjectClass *parent_class = NULL;

struct PPViewToolbarPrivate
{
	GaleonWindow *window;
	EggDockItem *dock_item;
	GtkActionGroup *action_group;
	gboolean visibility;
	EmbedChromeMask old_chrome;
	int current_page;
	GaleonEmbed *embed;
};

static void 
toolbar_cmd_ppv_goto_first(GtkAction *action, 
	 		   PPViewToolbar *t);

static void 
toolbar_cmd_ppv_goto_last(GtkAction *action, 
			  PPViewToolbar *t);

static void 
toolbar_cmd_ppv_go_back(GtkAction *action, 
			PPViewToolbar *t);

static void 
toolbar_cmd_ppv_go_forward(GtkAction *action,
			   PPViewToolbar *t);

static void 
toolbar_cmd_ppv_close(GtkAction *action,
		      PPViewToolbar *t);

static void 
toolbar_cmd_ppv_print(GtkAction *action,
		      PPViewToolbar *t);

static GtkActionEntry ppv_entries[] = {
	{ "PPVGotoFirstAction", GTK_STOCK_GOTO_FIRST, N_("First"), NULL,
	  N_("Go to the first page"), G_CALLBACK(toolbar_cmd_ppv_goto_first) },
	{ "PPVGoBackAction", GTK_STOCK_GO_BACK, N_("Previous"), NULL,
	  N_("Go to the previous page"), G_CALLBACK(toolbar_cmd_ppv_go_back) },
	{ "PPVGoForwardAction", GTK_STOCK_GO_FORWARD, N_("Next"), NULL,
	  N_("Go to the next page"), G_CALLBACK(toolbar_cmd_ppv_go_forward) },
	{ "PPVGotoLastAction", GTK_STOCK_GOTO_LAST, N_("Last"), NULL,
	  N_("Go to the last page"), G_CALLBACK(toolbar_cmd_ppv_goto_last) },
	{ "PPVCloseAction", GTK_STOCK_CLOSE, N_("Close"), NULL,
	  N_("Leave print preview mode"), G_CALLBACK(toolbar_cmd_ppv_close) },
	{ "PPVPrintAction", GTK_STOCK_PRINT, N_("Print"), NULL,
	  N_("Print the current page"), G_CALLBACK(toolbar_cmd_ppv_print) }
};
static guint n_ppv_entries = G_N_ELEMENTS(ppv_entries);

GType 
ppview_toolbar_get_type (void)
{
        static GType ppview_toolbar_type = 0;

        if (ppview_toolbar_type == 0)
        {
                static const GTypeInfo our_info =
                {
                        sizeof (PPViewToolbarClass),
                        NULL, /* base_init */
                        NULL, /* base_finalize */
                        (GClassInitFunc) ppview_toolbar_class_init,
                        NULL,
                        NULL, /* class_data */
                        sizeof (PPViewToolbar),
                        0, /* n_preallocs */
                        (GInstanceInitFunc) ppview_toolbar_init
                };

                ppview_toolbar_type = g_type_register_static (G_TYPE_OBJECT,
						       "PPViewToolbar",
						       &our_info, 0);
        }

        return ppview_toolbar_type;

}

static void
ppview_toolbar_class_init (PPViewToolbarClass *klass)
{
        GObjectClass *object_class = G_OBJECT_CLASS (klass);

        parent_class = g_type_class_peek_parent (klass);

        object_class->finalize = ppview_toolbar_finalize;

	object_class->set_property = ppview_toolbar_set_property;
	object_class->get_property = ppview_toolbar_get_property;

	g_object_class_install_property (object_class,
                                         PROP_GALEON_WINDOW,
                                         g_param_spec_object ("GaleonWindow",
                                                              "GaleonWindow",
                                                              "Parent window",
                                                              GALEON_WINDOW_TYPE,
                                                              G_PARAM_READWRITE));
	g_object_class_install_property (object_class,
                                         PROP_DOCK_ITEM,
                                         g_param_spec_object ("EggDockItem",
                                                              "EggDockItem",
                                                              "Egg Dock item",
                                                              EGG_TYPE_DOCK_ITEM,
                                                              G_PARAM_READWRITE));


	signals[PRINT] =
		g_signal_new ("print",
			G_OBJECT_CLASS_TYPE (klass),
			G_SIGNAL_RUN_FIRST,
			G_STRUCT_OFFSET (PPViewToolbarClass, print),
			NULL, NULL,
			g_cclosure_marshal_VOID__VOID,
			G_TYPE_NONE,
			0);
}

static void
ppview_toolbar_set_property (GObject *object,
                      guint prop_id,
                      const GValue *value,
                      GParamSpec *pspec)
{
        PPViewToolbar *t = PPVIEW_TOOLBAR (object);

        switch (prop_id)
        {
                case PROP_GALEON_WINDOW:
                        ppview_toolbar_set_window (t, g_value_get_object (value));
                        break;
                case PROP_DOCK_ITEM:
                        ppview_toolbar_set_dock_item (t, g_value_get_object (value));
                        break;
        }
}

static void
ppview_toolbar_get_property (GObject *object,
                      guint prop_id,
                      GValue *value,
                      GParamSpec *pspec)
{
        PPViewToolbar *t = PPVIEW_TOOLBAR (object);

        switch (prop_id)
        {
                case PROP_GALEON_WINDOW:
                        g_value_set_object (value, t->priv->window);
                        break;
                case PROP_DOCK_ITEM:
                        g_value_set_object (value, t->priv->dock_item);
                        break;
        }
}

void
ppview_toolbar_set_dock_item (PPViewToolbar *t, EggDockItem *item)
{
	t->priv->dock_item = item;
}

static void
ppview_toolbar_set_window (PPViewToolbar *t, GaleonWindow *window)
{
	g_return_if_fail (t->priv->window == NULL);

	LOG ("ppview_toolbar_set_window");

	t->priv->window = window;

	t->priv->action_group = gtk_action_group_new("PPVActions");
	gtk_action_group_set_translation_domain (t->priv->action_group, NULL);

	gtk_action_group_add_actions(t->priv->action_group, ppv_entries,
				     n_ppv_entries, t);

	gtk_ui_manager_insert_action_group(window->merge,
					   t->priv->action_group, 0);
}

static void
ppview_toolbar_init (PPViewToolbar *t)
{
        t->priv = g_new0 (PPViewToolbarPrivate, 1);

	t->priv->window = NULL;
	t->priv->dock_item = NULL;
	t->priv->visibility = TRUE;
	t->priv->action_group = NULL;
}

static void
ppview_toolbar_finalize (GObject *object)
{
	PPViewToolbar *t;

        g_return_if_fail (object != NULL);
        g_return_if_fail (IS_PPVIEW_TOOLBAR (object));

	t = PPVIEW_TOOLBAR (object);

        g_return_if_fail (t->priv != NULL);

	g_object_unref(t->priv->action_group);

        g_free (t->priv);

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

PPViewToolbar *
ppview_toolbar_new (GaleonWindow *window)
{
	PPViewToolbar *t;

	t = PPVIEW_TOOLBAR (g_object_new (PPVIEW_TOOLBAR_TYPE, 
				   	  "GaleonWindow", window,
				   	  NULL));

	return t;
}

void
ppview_toolbar_set_old_chrome (PPViewToolbar *t, 
			       EmbedChromeMask chrome)
{
	t->priv->old_chrome = chrome;
}

static void
toolbar_update_sensitivity (PPViewToolbar *t)
{
	int pages = 0, c_page = 0;
	GaleonEmbed *embed = t->priv->embed;;
	
	if (embed)
	{
		galeon_embed_print_preview_num_pages (embed, &pages);
		c_page = t->priv->current_page;
	}

	g_object_set(G_OBJECT(ACTION_ITEM(PPV_GO_BACK_ACTION)),
		     "sensitive", c_page > 1, NULL);
	g_object_set(G_OBJECT(ACTION_ITEM(PPV_GOTO_FIRST_ACTION)),
		     "sensitive", c_page > 1, NULL);
	g_object_set(G_OBJECT(ACTION_ITEM(PPV_GO_FORWARD_ACTION)),
		     "sensitive", c_page < pages, NULL);
	g_object_set(G_OBJECT(ACTION_ITEM(PPV_GOTO_LAST_ACTION)),
		     "sensitive", c_page < pages, NULL);
}

static void
ppview_toolbar_close (PPViewToolbar *t)
{
	GaleonWindow *window = t->priv->window;
	GaleonEmbed *embed = t->priv->embed;

	g_return_if_fail (IS_GALEON_WINDOW (window));
	g_return_if_fail (IS_GALEON_EMBED (embed));

	/* This will call _set_visibility, and clear the embed */
	galeon_window_set_chrome (window, t->priv->old_chrome);
	
	galeon_embed_print_preview_close (embed);

	toolbar_update_sensitivity (t);
}

static gboolean
window_delete_event_cb (GaleonWindow *window, GdkEventAny *event, 
			PPViewToolbar *t)
{
	g_return_val_if_fail (t->priv->visibility, FALSE);

	/* We need to do this in any case, due to:
	 * http://bugzilla.mozilla.org/show_bug.cgi?id=241809 */
	ppview_toolbar_close (t);

	return TRUE;
}

void
ppview_toolbar_set_visibility (PPViewToolbar *t, gboolean visibility)
{
	if (visibility == t->priv->visibility) return;
	
	t->priv->visibility = visibility;

	g_return_if_fail (GTK_IS_WIDGET (t->priv->dock_item));

	if (visibility)
	{
		t->priv->current_page = 1;
		t->priv->embed = galeon_window_get_active_embed (t->priv->window);

		toolbar_update_sensitivity (t);

		g_signal_connect (t->priv->window, "delete-event",
				  G_CALLBACK (window_delete_event_cb), t);

		gtk_widget_show(GTK_WIDGET(t->priv->dock_item));
	}
	else
	{
		t->priv->embed = NULL;

		g_signal_handlers_disconnect_matched (t->priv->window,
			 G_SIGNAL_MATCH_DATA, 0, 0, NULL, NULL, t);

		gtk_widget_hide(GTK_WIDGET(t->priv->dock_item));
	}

}

static void 
toolbar_cmd_ppv_goto_first(GtkAction *action, 
			   PPViewToolbar *t)
{
	g_return_if_fail (IS_GALEON_EMBED (t->priv->embed));

	galeon_embed_print_preview_navigate (t->priv->embed,
					     PRINTPREVIEW_HOME, 0);

	t->priv->current_page = 1;

	toolbar_update_sensitivity (t);
}

static void 
toolbar_cmd_ppv_goto_last(GtkAction *action, 
			  PPViewToolbar *t)
{
	g_return_if_fail (IS_GALEON_EMBED (t->priv->embed));

	galeon_embed_print_preview_navigate (t->priv->embed, 
					     PRINTPREVIEW_END, 
					     0);

	galeon_embed_print_preview_num_pages (t->priv->embed, 
					      &t->priv->current_page);

	toolbar_update_sensitivity (t);
}

static void 
toolbar_cmd_ppv_go_back(GtkAction *action, 
			PPViewToolbar *t)
{
	g_return_if_fail (IS_GALEON_EMBED (t->priv->embed));

	t->priv->current_page --;

	galeon_embed_print_preview_navigate (t->priv->embed, 
					     PRINTPREVIEW_GOTO_PAGENUM,
					     t->priv->current_page);
	toolbar_update_sensitivity (t);
}

static void 
toolbar_cmd_ppv_go_forward(GtkAction *action, 
			   PPViewToolbar *t)
{
	g_return_if_fail (IS_GALEON_EMBED (t->priv->embed));
	
	t->priv->current_page ++;

	galeon_embed_print_preview_navigate (t->priv->embed,
					     PRINTPREVIEW_GOTO_PAGENUM,
					     t->priv->current_page);
	toolbar_update_sensitivity (t);
}

static void 
toolbar_cmd_ppv_close(GtkAction *action, 
		      PPViewToolbar *t)
{
	ppview_toolbar_close (t);
}

static void 
toolbar_cmd_ppv_print(GtkAction *action,
		      PPViewToolbar *t)
{
	ppview_toolbar_close (t);

	g_signal_emit (G_OBJECT (t), signals[PRINT], 0);
}
