/* GNOME INPUT METHOD PROPERTIES
 *
 * Copyright 2004 Sun Microsystems Inc.
 *
 * This is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library 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
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 * Boston, MA 02111-1307, USA.
 */

#include <config.h>
#include "status-placement.h"

#include <string.h>
#include <glib.h>
#include <gtk/gtk.h>
#include <gnome.h>
#include <gconf/gconf-client.h>
#include <glade/glade.h>
#include <stdarg.h>

/* Retrieve a widget from the Glade object */
#define WID(s) glade_xml_get_widget (dialog, s)

#define IM_KEY_DIR    "/desktop/gnome/input_methods"
#define ENABLE_IM_KEY IM_KEY_DIR "/support"
#define ENABLE_STATUS_KEY IM_KEY_DIR "/status"
#define ENABLE_LOOKUP_KEY IM_KEY_DIR "/lookup"
#define STATUS_PLACEMENT_KEY IM_KEY_DIR "/status_placement"
#define GTK_STATUS_STYLE_KEY "/desktop/gnome/interface/gtk-im-status-style"

typedef enum {
  IM_OFF = 0,
  IM_ON
} IMEnabled;

/* For gtk-im-status-style */
static const char *nothing = "nothing"; /* XIMStatusNothing */
static const char *callback = "callback"; /* XIMStatusCallbacks */
static const char *none = "none"; 	/* XIMStatusNone */

static const char *enabled = "enabled";
static const char *disabled = "disabled";

typedef struct {
  IMEnabled im_enabled;
  IMEnabled status_enabled;
  IMEnabled lookup_enabled;
  IMStatusPlacement status_placement;
} IMSettings;

static IMSettings current_setting;
static GdkAtom im_settings_atom = GDK_NONE;
static const char *_IM_SETTINGS = "_IM_SETTINGS";

static GladeXML *main_dialog;

static void setup_dialog (GladeXML *dialog);
static GladeXML *create_dialog (void);

static void
set_im_settings_property (GladeXML *dialog)
{
  GdkWindow *root_window = gdk_get_default_root_window ();

  if (im_settings_atom == GDK_NONE)
    im_settings_atom = gdk_atom_intern (_IM_SETTINGS, FALSE);
  if (im_settings_atom == GDK_NONE)
    return;

  gdk_property_change (root_window,
		       im_settings_atom, im_settings_atom,
		       8, GDK_PROP_MODE_REPLACE,
		       (guchar *)&current_setting, sizeof (IMSettings));
}

static void
im_toggled (GtkToggleButton *toggle_button,
	    GladeXML *dialog)
{
  GConfClient *client = gconf_client_get_default ();

  if (toggle_button == GTK_TOGGLE_BUTTON (WID ("im_enable_toggle")))
    {
      gboolean im_enabled = gtk_toggle_button_get_active (toggle_button);

      if ((current_setting.im_enabled == IM_ON && !im_enabled) ||
	  (current_setting.im_enabled == IM_OFF && im_enabled))
	{
	  GtkWidget *widget = WID ("im_appearance_box");
	  gtk_widget_set_sensitive (widget, im_enabled);
#ifdef HIDE_WHEN_DISABLED
	  if (im_enabled)
	    gtk_widget_show (widget);
	  else
	    gtk_widget_hide (widget);
#endif
	  gconf_client_set_string (client,
				   ENABLE_IM_KEY, 
				   im_enabled ?
				   enabled : disabled,
				   NULL);
	  current_setting.im_enabled = im_enabled ? IM_ON : IM_OFF;
	}
    }
  if (toggle_button == GTK_TOGGLE_BUTTON (WID ("im_status_toggle")))
    {
      gboolean status_enabled = gtk_toggle_button_get_active (toggle_button);

      if ((current_setting.status_enabled == IM_ON && !status_enabled) ||
	  (current_setting.status_enabled == IM_OFF && status_enabled))
	{
	  GtkWidget *widget = WID ("im_status_placement_box");
	  gtk_widget_set_sensitive (widget, status_enabled);
	  gconf_client_set_string (client,
				   ENABLE_STATUS_KEY,
				   status_enabled ?
				   enabled : disabled,
				   NULL);
	  current_setting.status_enabled = status_enabled;

	  if (status_enabled)
	    gconf_client_set_string (client,
				     GTK_STATUS_STYLE_KEY, 
				     current_setting.status_placement == ON_DESKTOP_PANEL ?
				     nothing : callback,
				     NULL);
	  else
	    gconf_client_set_string (client,
				     GTK_STATUS_STYLE_KEY, 
				     none,
				     NULL);
	}
    }
  if (toggle_button == GTK_TOGGLE_BUTTON (WID ("im_choice_toggle")))
    {
      gboolean lookup_enabled = gtk_toggle_button_get_active (toggle_button);

      if ((current_setting.lookup_enabled == IM_ON && !lookup_enabled) ||
	  (current_setting.lookup_enabled == IM_OFF && lookup_enabled))
	{
	  gconf_client_set_string (client,
				   ENABLE_LOOKUP_KEY,
				   lookup_enabled ?
				   enabled : disabled,
				   NULL);
	  current_setting.lookup_enabled = lookup_enabled;
	}
    }
  set_im_settings_property (dialog);
}

static void
im_status_placement_changed (GtkWidget *optionmenu,
			     GladeXML *dialog)
{
  GConfClient *client = gconf_client_get_default ();

  int status_placement;
  status_placement = gtk_option_menu_get_history (GTK_OPTION_MENU (optionmenu));
  if (status_placement != current_setting.status_placement)
    {
      gconf_client_set_string (client,
			       STATUS_PLACEMENT_KEY, 
			       gimlet_status_placement_name (status_placement),
			       NULL);
      current_setting.status_placement = status_placement;

      gconf_client_set_string (client,
			       GTK_STATUS_STYLE_KEY, 
			       status_placement == ON_DESKTOP_PANEL ?
			       nothing : callback,
			       NULL);
    }
  set_im_settings_property (dialog);
}

static void
revert_to_default (GtkDialog *dialog)
{
  GConfClient *client;
  client = gconf_client_get_default ();

  gconf_client_set_string (client,
			   ENABLE_IM_KEY, 
			   enabled,
			   NULL);
  gconf_client_set_string (client,
			   ENABLE_STATUS_KEY,
			   enabled,
			   NULL);
  gconf_client_set_string (client,
			   STATUS_PLACEMENT_KEY, 
			   DEFAULT_STATUS_PLACEMENT,
			   NULL);
  gconf_client_set_string (client,
			   GTK_STATUS_STYLE_KEY, 
			   nothing,
			   NULL);
  gconf_client_set_string (client,
			   ENABLE_LOOKUP_KEY,
			   enabled,
			   NULL);
  current_setting.im_enabled = IM_ON;
  current_setting.status_enabled = IM_ON;
  current_setting.lookup_enabled = IM_ON;
  current_setting.status_placement = gimlet_status_placement (DEFAULT_STATUS_PLACEMENT);

  setup_dialog (main_dialog);
}

static void
cb_dialog_response (GtkDialog *dialog, gint response_id)
{
  if (response_id == GTK_RESPONSE_CLOSE)
    gtk_main_quit ();
  else if (response_id == GTK_RESPONSE_HELP)
	 {
	   GError *error = NULL;

	   gnome_help_display_desktop (
			 NULL, "imswitcher", "imswitcher.xml", 
			 NULL, &error);

	   if (error)
	     {
	       GtkWidget *message_dialog;
	       message_dialog = gtk_message_dialog_new (NULL, 0,
							GTK_MESSAGE_ERROR,
							GTK_BUTTONS_OK,
							_("There was an error displaying help: %s"),
							error->message);
	       g_error_free (error);
	       gtk_dialog_run (GTK_DIALOG (message_dialog));
	       gtk_widget_destroy (message_dialog);
	     }
	   }
  else
    revert_to_default (dialog);
}

static void
setup_dialog (GladeXML *dialog)
{
  GConfClient *client;
  GtkWidget *widget;
  GtkTooltips *tooltips;
  gboolean im_enabled, status_enabled, lookup_enabled;
  char *str = NULL;

  client = gconf_client_get_default ();

  str = NULL;
  str = gconf_client_get_string (client,
				 ENABLE_IM_KEY, NULL);
  if (str && strcmp (str, disabled) == 0)
    im_enabled = FALSE;
  else
    im_enabled = TRUE;
  g_free (str);

  str = NULL;
  str = gconf_client_get_string (client,
				 ENABLE_STATUS_KEY, NULL);
  if (str && strcmp (str, disabled) == 0)
    status_enabled = FALSE;
  else
    status_enabled = TRUE;
  g_free (str);

  str = NULL;
  str = gconf_client_get_string (client,
				 ENABLE_LOOKUP_KEY, NULL);
  if (str && strcmp (str, disabled) == 0)
    lookup_enabled = FALSE;
  else
    lookup_enabled = TRUE;
  g_free (str);

  current_setting.im_enabled = im_enabled ? IM_ON : IM_OFF;
  current_setting.status_enabled = status_enabled ? IM_ON : IM_OFF;
  current_setting.lookup_enabled = lookup_enabled ? IM_ON : IM_OFF;

  str = NULL;
  str = gconf_client_get_string (client,
				 STATUS_PLACEMENT_KEY, NULL);
  current_setting.status_placement = gimlet_status_placement (str);
  g_free (str);

  set_im_settings_property (dialog);

  tooltips = gtk_tooltips_new();

  widget = WID ("im_appearance_box");
  gtk_widget_set_sensitive (widget, im_enabled);

#ifdef HIDE_WHEN_DISABLED
  if (im_enabled)
    gtk_widget_show (widget);
  else
    gtk_widget_hide (widget);
#endif

  gtk_widget_set_sensitive (WID ("im_status_placement_box"), status_enabled);

  /* im enable toggle button */
  widget = WID ("im_enable_toggle");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), im_enabled);
  g_signal_connect (widget, "toggled",
		    G_CALLBACK (im_toggled), 
		    dialog);
  gtk_tooltips_set_tip (tooltips, widget,
			_("Changes to this setting will immediately take effect on the current session."),
			NULL);
  
  /* im status toggle button */
  widget = WID ("im_status_toggle");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), status_enabled);
  g_signal_connect (widget, "toggled",
		    G_CALLBACK (im_toggled), 
		    dialog);
  gtk_tooltips_set_tip (tooltips, widget,
			_("Changes to this setting will immediately take effect on the current session."),
			NULL);

  /* im status placement option menu */
  widget = WID ("status_placement_menu");
  gtk_option_menu_set_history (GTK_OPTION_MENU (widget),
			       current_setting.status_placement);
  g_signal_connect (widget, "changed",
		    G_CALLBACK (im_status_placement_changed),
		    dialog);

  /* im choice toggle button */
  widget = WID ("im_choice_toggle");
  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (widget), lookup_enabled);
  g_signal_connect (widget, "toggled",
		    G_CALLBACK (im_toggled), 
		    dialog);
  gtk_tooltips_set_tip (tooltips, widget,
			_("Changes to this setting may not be effective in some languages and input method editors."),
			NULL);

  /* response close, help, revert button events */
  widget = WID ("im_properties_dialog");
  g_signal_connect (G_OBJECT (widget),
		    "response",
		    G_CALLBACK (cb_dialog_response), NULL);

  g_signal_connect (G_OBJECT(widget), "destroy", 
		    G_CALLBACK (gtk_main_quit), NULL);

  gtk_widget_show (widget);

}

static GladeXML *
create_dialog (void)
{
  GladeXML *dialog;

  dialog = glade_xml_new (GNOMECC_DATA_DIR "/interfaces/gnome-im-properties.glade2", "im_properties_dialog", NULL);

#ifdef INCLUDE_ICON_IN_CAPPLET_WINDOW
  gtk_image_set_from_file (GTK_IMAGE (WID ("im_enable_image")),
			   PIXMAPDIR "/gnome-settings-im.png");
#endif

  return dialog;
}

int
main (int argc, char *argv[])
{
  bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
  textdomain (GETTEXT_PACKAGE);

  gnome_program_init ("gnome-im-properties", VERSION,
		      LIBGNOMEUI_MODULE, argc, argv,
		      GNOME_PARAM_APP_DATADIR, GNOMECC_DATA_DIR,
		      NULL);

  main_dialog = create_dialog ();
  setup_dialog (main_dialog);

  gtk_main ();
  return 0;
}
