/*
 * Copyright (c) 2003, 2004 Jean-Yves Lefort
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Jean-Yves Lefort nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGE.
 */

#include "config.h"
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <stdarg.h>
#include "sg-util.h"
#include "sgtk-auth-dialog.h"
#include "sgtk-hig.h"

/*** type definitions ********************************************************/

struct _sGtkAuthDialogPrivate
{
  GtkWidget	*label;
  GtkWidget	*name_entry;
  GtkWidget	*password_entry;
};

/*** function declarations ***************************************************/

static void sgtk_auth_dialog_class_init	(sGtkAuthDialogClass	*class);
static void sgtk_auth_dialog_init	(sGtkAuthDialog		*dialog);

static void sgtk_auth_dialog_update_sensitivity (sGtkAuthDialog *dialog);
static void sgtk_auth_dialog_entry_activate_h	(GtkEntry	*entry,
						 gpointer	user_data);
     
/*** implementation **********************************************************/

GType
sgtk_auth_dialog_get_type (void)
{
  static GType auth_dialog_type = 0;
  
  if (! auth_dialog_type)
    {
      static const GTypeInfo auth_dialog_info = {
	sizeof(sGtkAuthDialogClass),
	NULL,
	NULL,
	(GClassInitFunc) sgtk_auth_dialog_class_init,
	NULL,
	NULL,
	sizeof(sGtkAuthDialog),
	0,
	(GInstanceInitFunc) sgtk_auth_dialog_init,
      };
      
      auth_dialog_type = g_type_register_static(SGTK_TYPE_ALERT_DIALOG,
						"sGtkAuthDialog",
						&auth_dialog_info,
						0);
    }

  return auth_dialog_type;
}

static void
sgtk_auth_dialog_class_init (sGtkAuthDialogClass *class)
{
  g_type_class_add_private(class, sizeof(sGtkAuthDialogPrivate));
}

static void
sgtk_auth_dialog_init (sGtkAuthDialog *dialog)
{
  GtkWidget *table;
  GtkWidget *name_label;
  GtkWidget *password_label;

  dialog->priv = G_TYPE_INSTANCE_GET_PRIVATE(dialog, SGTK_TYPE_AUTH_DIALOG, sGtkAuthDialogPrivate);

  gtk_dialog_add_buttons(GTK_DIALOG(dialog),
			 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
			 _("_Authenticate"), GTK_RESPONSE_OK,
			 NULL);
  gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK);

  gtk_image_set_from_stock(GTK_IMAGE(SGTK_ALERT_DIALOG(dialog)->image),
			   GTK_STOCK_DIALOG_AUTHENTICATION,
			   GTK_ICON_SIZE_DIALOG);

  dialog->priv->label = gtk_label_new(NULL);

  gtk_misc_set_alignment(GTK_MISC(dialog->priv->label),
			 SGTK_HIG_ALERT_LABEL_X_ALIGN,
			 SGTK_HIG_ALERT_LABEL_Y_ALIGN);
  gtk_label_set_line_wrap(GTK_LABEL(dialog->priv->label), TRUE);
  gtk_label_set_selectable(GTK_LABEL(dialog->priv->label), TRUE);

  name_label = gtk_label_new_with_mnemonic(_("_Name:"));
  dialog->priv->name_entry = gtk_entry_new();

  password_label = gtk_label_new_with_mnemonic(_("_Password:"));
  dialog->priv->password_entry = gtk_entry_new();

  gtk_label_set_mnemonic_widget(GTK_LABEL(name_label), dialog->priv->name_entry);
  gtk_label_set_mnemonic_widget(GTK_LABEL(password_label), dialog->priv->password_entry);

  gtk_misc_set_alignment(GTK_MISC(name_label), 0, 0.5);
  gtk_misc_set_alignment(GTK_MISC(password_label), 0, 0.5);
  gtk_entry_set_visibility(GTK_ENTRY(dialog->priv->password_entry), FALSE);

  g_object_connect(dialog->priv->name_entry,
		   "swapped-signal::changed", sgtk_auth_dialog_update_sensitivity, dialog,
		   "signal::activate", sgtk_auth_dialog_entry_activate_h, dialog->priv->password_entry,
		   NULL);
  g_object_connect(dialog->priv->password_entry,
		   "swapped-signal::changed", sgtk_auth_dialog_update_sensitivity, dialog,
		   "signal::activate", sgtk_auth_dialog_entry_activate_h, dialog->priv->name_entry,
		   NULL);

  table = gtk_table_new(3, 2, FALSE);

  gtk_table_set_row_spacings(GTK_TABLE(table), SGTK_HIG_CONTROL_SPACING);
  gtk_table_set_col_spacings(GTK_TABLE(table), SGTK_HIG_CONTROL_LABEL_SPACING);
  
  /* spacing between dialog label and controls */
  gtk_table_set_row_spacing(GTK_TABLE(table), 0, SGTK_HIG_DIALOG_CONTENTS_SPACING);

  gtk_table_attach(GTK_TABLE(table), dialog->priv->label, 0, 2, 0, 1,
		   GTK_FILL,
		   (GtkAttachOptions) 0,
		   0,
		   0);
  
  gtk_table_attach(GTK_TABLE(table), name_label, 0, 1, 1, 2,
		   GTK_FILL,
		   (GtkAttachOptions) 0,
		   0,
		   0);
  gtk_table_attach(GTK_TABLE(table), dialog->priv->name_entry, 1, 2, 1, 2,
		   GTK_EXPAND | GTK_FILL,
		   (GtkAttachOptions) 0,
		   0,
		   0);

  gtk_table_attach(GTK_TABLE(table), password_label, 0, 1, 2, 3,
		   GTK_FILL,
		   (GtkAttachOptions) 0,
		   0,
		   0);
  gtk_table_attach(GTK_TABLE(table), dialog->priv->password_entry, 1, 2, 2, 3,
		   GTK_EXPAND | GTK_FILL,
		   (GtkAttachOptions) 0,
		   0,
		   0);
 
  gtk_box_pack_start(GTK_BOX(SGTK_ALERT_DIALOG(dialog)->hbox), table, FALSE, FALSE, 0);

  gtk_widget_show_all(table);
}

static void
sgtk_auth_dialog_update_sensitivity (sGtkAuthDialog *dialog)
{
  const char *name;
  const char *password;

  g_return_if_fail(SGTK_IS_AUTH_DIALOG(dialog));

  name = gtk_entry_get_text(GTK_ENTRY(dialog->priv->name_entry));
  password = gtk_entry_get_text(GTK_ENTRY(dialog->priv->password_entry));

  gtk_dialog_set_response_sensitive(GTK_DIALOG(dialog), GTK_RESPONSE_OK, *name && *password);
}

static void
sgtk_auth_dialog_entry_activate_h (GtkEntry *entry, gpointer user_data)
{
  GtkWidget *next = user_data;
  GtkWidget *toplevel;

  toplevel = gtk_widget_get_toplevel(GTK_WIDGET(entry));
  if (GTK_WIDGET_TOPLEVEL(toplevel)
      && GTK_WINDOW(toplevel)->default_widget
      && GTK_WIDGET_IS_SENSITIVE(GTK_WINDOW(toplevel)->default_widget))
    gtk_window_activate_default(GTK_WINDOW(toplevel));
  else if (GTK_WIDGET_IS_SENSITIVE(next))
    gtk_widget_grab_focus(next);
}

GtkWidget *
sgtk_auth_dialog_new (GtkWindow *parent,
		      const char *default_name,
		      const char *default_password,
		      const char *primary,
		      const char *format,
		      ...)
{
  sGtkAuthDialog *dialog;
  GString *message;

  dialog = g_object_new(SGTK_TYPE_AUTH_DIALOG, NULL);

  if (parent)
    gtk_window_set_transient_for(GTK_WINDOW(dialog), parent);
  
  message = g_string_new(NULL);
  if (primary)
    sg_string_append_printf_escaped(message,
				    "<span weight=\"bold\" size=\"larger\">%s</span>",
				    primary);

  if (format)
    {
      va_list args;

      if (primary)
	g_string_append(message, "\n\n");

      va_start(args, format);
      sg_string_append_vprintf_escaped(message, format, args);
      va_end(args);
    }
  
  gtk_label_set_markup(GTK_LABEL(dialog->priv->label), message->str);
  g_string_free(message, TRUE);

  gtk_entry_set_text(GTK_ENTRY(dialog->priv->name_entry), default_name ? default_name : "");
  gtk_entry_set_text(GTK_ENTRY(dialog->priv->password_entry), default_password ? default_password : "");

  if (! default_name)
    gtk_widget_grab_focus(dialog->priv->name_entry);
  else if (! default_password)
    gtk_widget_grab_focus(dialog->priv->password_entry);

  sgtk_auth_dialog_update_sensitivity(dialog);

  return GTK_WIDGET(dialog);
}

void
sgtk_auth_dialog_set_name_sensitive (sGtkAuthDialog *dialog,
				     gboolean sensitive)
{
  g_return_if_fail(SGTK_IS_AUTH_DIALOG(dialog));

  gtk_widget_set_sensitive(dialog->priv->name_entry, sensitive);
}

const char *
sgtk_auth_dialog_get_name (sGtkAuthDialog *dialog)
{
  g_return_val_if_fail(SGTK_IS_AUTH_DIALOG(dialog), NULL);

  return gtk_entry_get_text(GTK_ENTRY(dialog->priv->name_entry));
}

const char *
sgtk_auth_dialog_get_password (sGtkAuthDialog *dialog)
{
  g_return_val_if_fail(SGTK_IS_AUTH_DIALOG(dialog), NULL);

  return gtk_entry_get_text(GTK_ENTRY(dialog->priv->password_entry));
}
