/*
 * CookiePromptService.cpp
 *
 * Copyright (C) 2003 Tommi Komulainen <tommi.komulainen@iki.fi>
 * Available under the terms of the GNU General Public License version 2.
 */ 

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "MozillaPrivate.h"
#include "gul-glade.h"
#include "galeon-embed-shell.h"
#include "mozilla-cookie.h"
#include "nsString.h"

#include <gtk/gtkdialog.h>
#include <gtk/gtklabel.h>
#include <gtk/gtkhbox.h>
#include <gtk/gtkalignment.h>
#include <gtk/gtkimage.h>
#include <gtk/gtkexpander.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtkcheckbutton.h>

#include <libgnome/gnome-triggers.h>
#include <glib/gi18n.h>
#include <libgnome/gnome-config.h>

#include "CookiePromptService.h"
#include "hig-alert.h"
#include "gul-state.h"

/* gnome-config keys for saving state */
#define STATE_COOKIE_REMEMBER_DECISION "Cookie/remember_decision"
#define STATE_COOKIE_SHOW_DETAILS      "Cookie/show_details"

NS_IMPL_ISUPPORTS1(GCookiePromptService, nsICookiePromptService)

GCookiePromptService::GCookiePromptService()
{
}

GCookiePromptService::~GCookiePromptService()
{
}

static void
GCookiePromptService_button_toggled (GtkExpander *expander, GParamSpec *pspec, GtkWindow *dialog)
{
	gboolean val = gtk_expander_get_expanded (expander);
	gtk_window_set_resizable (dialog, val);
}

static char*
make_secondary_text (const char *aHost, PRBool aModify, PRInt32 aCount)
{
	char *ttHost = g_strdup_printf ("<tt>\"%s\"</tt>",  aHost);
	char *question;
	if (aModify)
	{
		question = g_strdup_printf
			(_("The site %s wants to modify an existing cookie."),
			 ttHost);
	}
	else if (aCount == 0)
	{
		question = g_strdup_printf
			(_("The site %s wants to set a cookie."), ttHost);
	}
	else if (aCount == 1)
	{
		question = g_strdup_printf
			(_("The site %s wants to set a second cookie."), ttHost);
	}
	else
	{
		question = g_strdup_printf
		  (ngettext("The site %s wants to set another cookie."
			    " You already have %d cookie from this site.",
			    "The site %s wants to set another cookie."
			    " You already have %d cookies from this site.",
			    aCount),
			 ttHost, aCount);
	}

	g_free (ttHost);

	return question;
}

static GtkWidget *
higgy_indent_widget (GtkWidget *widget)
{
	GtkWidget *hbox;
	GtkWidget *label;

	hbox = gtk_hbox_new (FALSE, 6);

	label = gtk_label_new ("");
	gtk_box_pack_start (GTK_BOX(hbox), label, FALSE, TRUE, 6);
	gtk_widget_show (label);

	gtk_box_pack_start (GTK_BOX(hbox), widget, TRUE, TRUE, 0);

	return hbox;
}


static GtkWidget *
create_button_with_image (const gchar *text, const gchar *stock_icon)
{
	GtkWidget *button, *align, *hbox, *image, *label;

	button = gtk_button_new ();
	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);

	align = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
	gtk_container_add (GTK_CONTAINER (button), align);

	hbox = gtk_hbox_new (FALSE, 2);
	gtk_container_add (GTK_CONTAINER (align), hbox);

	image = gtk_image_new_from_stock (stock_icon, GTK_ICON_SIZE_BUTTON);
	gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);

	label = gtk_label_new_with_mnemonic (text);
	gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);

	gtk_widget_show_all (button);
	return button;
}


/* boolean cookieDialog (in nsIDOMWindow parent, in nsICookie cookie, in ACString hostname, in long cookiesFromHost, in boolean changingCookie, inout boolean checkValue); */
NS_IMETHODIMP GCookiePromptService::CookieDialog(nsIDOMWindow *aParent, nsICookie *aCookie, const nsACString & aHostname, PRInt32 aCookiesFromHost, PRBool aChangingCookie, PRBool *_checkValue, PRBool *_retval)
{
	// TODO short-circuit and accept session cookies as per preference
	// TODO until mozilla starts supporting it natively?

	GtkWidget *dialog, *button;
        gboolean checkValue;

	GtkWidget *gparent = MozillaFindGtkParent (aParent);

	dialog = hig_alert_new (GTK_WINDOW (gparent),
				(GtkDialogFlags)NULL,
				HIG_ALERT_CONFIRMATION,
				NULL, NULL,
				NULL);

	button = create_button_with_image (_("_Reject"), GTK_STOCK_NO);
	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_REJECT);

	button = create_button_with_image (_("_Accept"), GTK_STOCK_YES);
	gtk_dialog_add_action_widget (GTK_DIALOG (dialog), button, GTK_RESPONSE_ACCEPT);
	gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);

	// Set up the text
	hig_alert_set_primary_printf (HIG_ALERT (dialog), _("Accept cookie from %s?"), 
				      PromiseFlatCString(aHostname).get());

	char *secondary = make_secondary_text (PromiseFlatCString(aHostname).get(), 
			                       aChangingCookie, aCookiesFromHost);

	hig_alert_set_secondary_printf (HIG_ALERT (dialog), "%s", secondary);
	g_free(secondary);

	// Set up the checkbox
	GtkWidget *checkbutton = gtk_check_button_new_with_mnemonic 
		                (_("R_emember this decision for this site"));

	gtk_widget_show (checkbutton);
	hig_alert_add_widget (HIG_ALERT (dialog), checkbutton);

        /* In Mozilla 1.4+ they changed the _checkValue from read/write to write only,
         * so mozilla does not store the state for us, we need to do it :( */
	checkValue = gnome_config_get_bool (STATE_COOKIE_REMEMBER_DECISION "=false");
	gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(checkbutton), checkValue);

	// add the expander button and the cookie details table
	button = gtk_expander_new_with_mnemonic (_("Cookie _Details:"));
	gtk_widget_show (button);
	gtk_box_pack_start (GTK_BOX(GTK_DIALOG(dialog)->vbox), button, FALSE, FALSE, 0);

	CookieInfo *info = mozilla_cookie_to_info (aCookie);
	GtkWidget *details = cookie_info_table_new (info);
	cookie_info_free (info);

	details = higgy_indent_widget (details);
	gtk_widget_show (details);
	gtk_container_add (GTK_CONTAINER (button), details );

	g_signal_connect (G_OBJECT(button), "notify::expanded", 
			  G_CALLBACK(GCookiePromptService_button_toggled), 
			  dialog);

	gul_state_monitor_expander (button, STATE_COOKIE_SHOW_DETAILS, FALSE);

	// for convenience, make ESC close the dialog
	g_signal_connect (dialog, "close", 
			  G_CALLBACK (gtk_dialog_response), 
			  GINT_TO_POINTER (GTK_RESPONSE_CLOSE));

	// run and handle the response
	gnome_triggers_vdo ("", "question", NULL);
	gint ret = gtk_dialog_run (GTK_DIALOG(dialog));
	if (ret == GTK_RESPONSE_ACCEPT || ret == GTK_RESPONSE_REJECT)
	{
		*_retval = (ret == GTK_RESPONSE_ACCEPT);
		*_checkValue = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON(checkbutton));

                /* Save the value of this check box */
		gnome_config_set_bool (STATE_COOKIE_REMEMBER_DECISION, *_checkValue);
	}
	else
	{
		// if the dialog was closed, but no button was pressed,
		// consider it as 'Reject' but ignore the checkbutton
		*_retval = PR_FALSE;
		*_checkValue = PR_FALSE;
	}

	// done
	gtk_widget_destroy (dialog);
	return NS_OK;
}
