/* GIMLET: GNOME Input Method Language Enabing Tool
 *
 * Copyright 2003 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 <gtk/gtkmain.h>
#include <gtk/gtkdrawingarea.h>
#include <gtk/gtkbutton.h>
#include <gtk/gtksignal.h>
#include <libart_lgpl/libart.h>
#include <panel-applet.h>
#include <gnome.h>

#include <signal.h>
#include <wait.h>

#include "gnome-im-switcher.h"
#include "iiim-interface.h"
#include "language.h"
#include "preference.h"
#include "quick-access-menu.h"
#include "utils.h"
#include "widgets.h"

static void
help_verb_cb (BonoboUIComponent *uic,
	      GimletWindow *gimlet,
	      const gchar *verbname)
{
	gimlet_util_show_help ("index", GTK_WINDOW (gimlet->applet));
}

static void
edit_preferences_destroyed_cb (GtkWidget   *new_profile_dialog,
			       GimletWindow *gimlet)
{
  gimlet->edit_preferences_dialog = NULL;
}

static void
show_preferences_dialog (BonoboUIComponent *uic,
			 GimletWindow *gimlet,
			 const gchar       *verbname)
{
  GtkWindow *transient_parent;
  GtkWindow *old_transient_parent;

  transient_parent = GTK_WINDOW (gimlet->applet);
  if (gimlet->edit_preferences_dialog == NULL)
    {
      old_transient_parent = NULL;
      /* passing in transient_parent here purely for the
       * glade error dialog
       */
      gimlet->edit_preferences_dialog =
	gimlet_preference_dialog_new (transient_parent, gimlet);
      if (gimlet->edit_preferences_dialog == NULL)
        return; /* glade file missing */
      
      g_signal_connect (G_OBJECT (gimlet->edit_preferences_dialog),
                        "destroy",
                        G_CALLBACK (edit_preferences_destroyed_cb),
                        gimlet);
    }
  else
    {
      old_transient_parent = gtk_window_get_transient_for (GTK_WINDOW (gimlet->edit_preferences_dialog));
    }
  if (old_transient_parent != transient_parent)
    {
      gtk_window_set_transient_for (GTK_WINDOW (gimlet->edit_preferences_dialog),
                                    transient_parent);
      gtk_widget_hide (gimlet->edit_preferences_dialog); /* re-show the window on its new parent */
    }
  
  gtk_widget_show_all (gimlet->edit_preferences_dialog);
  gtk_window_present (GTK_WINDOW (gimlet->edit_preferences_dialog));
  return;
}

static void
about_verb_cb (BonoboUIComponent *uic,
	       GimletWindow *gimlet,
	       const gchar *verbname)
{
  gchar **authors;
  const gchar *documenters[] = {
    NULL
  };
  const char *translator_credits = _("translator_credits");
  char *file;

  authors = g_new (gchar*, 3);
  authors[0] = g_strdup(_("Hidetoshi Tajima <hidetoshi.tajima@sun.com>"));
  authors[1] = g_strdup("Jens Petersen <petersen@redhat.com>");
  authors[2] = NULL;

  if (gimlet->about_dialog != NULL) {
    gtk_window_present (GTK_WINDOW (gimlet->about_dialog));
    return;
  }

  file = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
				    _("gnome-settings-im.png"),
				    TRUE, NULL);
  if (file)
    {
      GdkPixbuf *pixbuf = NULL;
      pixbuf = gdk_pixbuf_new_from_file (file, NULL);
      gtk_window_set_icon (GTK_WINDOW (gimlet->about_dialog), pixbuf);
      g_object_unref (pixbuf);
      g_free (file);
    }

  gimlet->about_dialog = gnome_about_new (_("Gnome Input Method Switcher"),
					  VERSION,
					  "Copyright \xc2\xa9 2002-2004 Sun Microsystems, Inc.\nCopyright \xc2\xa9 2002,2004 Red Hat, Inc.",
					  _("Switch Input Languages on the panel."),
					  (const gchar**)authors,
					  documenters,
					  strcmp (translator_credits, "translator_credits") != 0 ? translator_credits : NULL,
					  NULL);
  gtk_signal_connect (GTK_OBJECT(gimlet->about_dialog),
		      "destroy",
                      GTK_SIGNAL_FUNC(gtk_widget_destroyed),
		      &gimlet->about_dialog);

  g_strfreev (authors);
  gtk_widget_show (gimlet->about_dialog);
}

static const BonoboUIVerb menu_verbs [] = {
  BONOBO_UI_UNSAFE_VERB ("Props",	show_preferences_dialog),
  BONOBO_UI_UNSAFE_VERB ("Help",        help_verb_cb),
  BONOBO_UI_UNSAFE_VERB ("About",	about_verb_cb),
  BONOBO_UI_VERB_END
};

static gboolean 
key_press_cb (GtkWidget *widget, GdkEventKey *event,
	      GimletWindow *gimlet)
{
  switch (event->keyval)
    {
    case GDK_KP_Enter:
    case GDK_ISO_Enter:
    case GDK_3270_Enter:
    case GDK_Return:
    case GDK_space:
    case GDK_KP_Space:
      gimlet_quick_access_menu_show (gimlet);
      return TRUE;
      break;
    default:
      break;
    }
  return FALSE;
}

static gboolean 
handle_button_release (GimletWindow *gimlet,
		       GdkEventButton *event)
{
  if (event->button != 1)
    return FALSE; 

  gimlet_quick_access_menu_show (gimlet);
  return TRUE;
}

static GdkPixbuf *
init_pixbuf (const gchar *name)
{
  GdkPixbuf *pixbuf;
  GError    *error = NULL;
  char      *path = NULL;

  path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_PIXMAP,
				    name, FALSE, NULL);
  if (!path)
    path = gnome_program_locate_file (NULL, GNOME_FILE_DOMAIN_APP_PIXMAP,
				      name, FALSE, NULL);
  if (!path)
	 return NULL;

  pixbuf = gdk_pixbuf_new_from_file (path, &error);

  if (error)
    {
      g_warning ("Cannot load '%s': %s", path, error->message);
      g_error_free (error);
    }
  g_free (path);
  return pixbuf;
 }

static GdkPixbuf *on_pixbuf;
static GdkPixbuf *off_pixbuf;
static GdkPixbuf *disabled_pixbuf;

void
icon_set_text (GimletWindow *gimlet)
{
  GdkPixbuf *pixbuf;
  if (gimlet->im_enabled)
    if (gimlet->conversion_mode)
      pixbuf = on_pixbuf;
    else
      pixbuf = off_pixbuf;
  else
    pixbuf = disabled_pixbuf;

  GtkWidget *drawing = gimlet->drawing_area;
  GdkGC *gc = gdk_gc_new(GDK_WINDOW(drawing->window));
  gdk_draw_pixbuf(GDK_WINDOW(drawing->window),
		  gc,
		  pixbuf,
		  0,0,0,0,-1,-1,
		  GDK_RGB_DITHER_NONE,
		  0,0);
  if (gimlet->im_enabled)
    {
      gchar *text = gimlet_language_find_short (gimlet->current_iiim_lang);
      PangoLayout *layout = gtk_widget_create_pango_layout (GTK_WIDGET(drawing), text);

      int height = gdk_pixbuf_get_height(pixbuf);
      int width = gdk_pixbuf_get_width(pixbuf);
      int pango_width, pango_height, x_pos;
      pango_layout_get_pixel_size (layout, &pango_width, &pango_height);
      if (width > pango_width)
	x_pos = (width-pango_width)/2;
      else
	x_pos = 0;
      gdk_draw_layout (GDK_WINDOW(drawing->window),
		       gc,
		       x_pos,
		       ((height-pango_height)/2),
		       layout);
      g_free (text);
    }
}

void
update_tooltips (GimletWindow *gimlet)
{
  gchar *lang;
  gchar *name;
  gchar *descr;
  gchar *text;

  lang = gimlet->current_iiim_lang;

  if (lang)
    {
      name = gimlet_language_find_name (lang);
      descr = _(gimlet_language_find_description (lang));
      if (name && descr && strcmp (name, descr) == 0)
	text = g_strdup (name);
      else
	text = g_strconcat (name, " - ", descr, NULL);
      gtk_tooltips_set_tip (gimlet->tooltips, GTK_WIDGET(gimlet->applet), text, NULL);
      g_free(text);
    }
}

gboolean
drawing_area_expose_cb (GtkWidget *widget,
			GdkEventExpose *event,
			GimletWindow *gimlet)
{
  icon_set_text (gimlet);
  update_tooltips (gimlet);
  return TRUE;
}

static void
place_widgets (GimletWindow *gimlet)
{
  GtkWidget *box = NULL;
  GtkWidget *lang_box = NULL;

  switch (panel_applet_get_orient (PANEL_APPLET (gimlet->applet))) {
  case PANEL_APPLET_ORIENT_DOWN:
  case PANEL_APPLET_ORIENT_UP:
    box = gtk_hbox_new (FALSE, 3);
    lang_box = gtk_vbox_new (FALSE, 3);
    break;
  case PANEL_APPLET_ORIENT_LEFT:
  case PANEL_APPLET_ORIENT_RIGHT:
    box = gtk_vbox_new (FALSE, 3);
    lang_box = gtk_hbox_new (FALSE, 3);
    break;
  }

  gtk_container_add (GTK_CONTAINER (gimlet->applet), box);
  gtk_widget_show (box);
  gtk_box_pack_end_defaults (GTK_BOX(box), GTK_WIDGET(lang_box));
  gtk_widget_show (GTK_WIDGET (lang_box));

  /* initialize language by guessing from locale */
  gchar *locale = getenv ("LC_CTYPE");
  if (! locale)
    locale = getenv ("LANG");
  gchar *lang;

  if (locale)
    {
      lang = g_strndup (locale, 5);
      if (! gimlet_language_find_short (lang))
	{
	  lang = g_strndup (locale, 2);
	  if (! gimlet_language_find_short (lang))
	        lang = g_strdup ("en");
	}
    }
  if (! lang)
    lang = g_strdup ("en");
  
  gimlet->current_iiim_lang = lang;

  on_pixbuf = init_pixbuf ("gimlet-on.png");
  off_pixbuf = init_pixbuf ("gimlet-off.png");
  disabled_pixbuf = init_pixbuf ("gimlet-disable.png");

  gimlet->drawing_area = gtk_drawing_area_new ();
  int width = gdk_pixbuf_get_width(off_pixbuf);
  int height = gdk_pixbuf_get_height(off_pixbuf);
  gtk_widget_set_size_request (GTK_WIDGET(gimlet->drawing_area), width, height);
  g_signal_connect (G_OBJECT (gimlet->drawing_area), "expose_event",  
                    G_CALLBACK (drawing_area_expose_cb), gimlet);
  gtk_widget_show (gimlet->drawing_area);
  
  gtk_box_pack_start (GTK_BOX(lang_box), GTK_WIDGET(gimlet->drawing_area),
		      TRUE, FALSE, 0);

  gimlet->tooltips = gtk_tooltips_new();
  gimlet_update_lang (gimlet);

  gimlet->status_label = gtk_label_new (NULL);
  gtk_box_pack_start_defaults (GTK_BOX (box),
			       GTK_WIDGET(gimlet->status_label));
  gimlet_status_set_text (gimlet, "");

  g_signal_connect_swapped (G_OBJECT(gimlet->applet), "button_release_event",
			    G_CALLBACK (handle_button_release), gimlet);

  gtk_container_set_border_width (GTK_CONTAINER (gimlet->applet), 0);

  gtk_widget_show (GTK_WIDGET (gimlet->applet));
}

/* public */
void
gimlet_init (GimletWindow *gimlet)
{
  panel_applet_set_flags (gimlet->applet, PANEL_APPLET_EXPAND_MINOR);

  g_signal_connect (G_OBJECT(gimlet->applet), "key_press_event",
		    G_CALLBACK(key_press_cb), gimlet);
                     
  panel_applet_setup_menu_from_file (gimlet->applet,
				     NULL,
				     "GNOME_InputMethodSwitcherApplet.xml",
				     NULL,
				     menu_verbs,
				     gimlet);
#ifdef GNOME_PANEL_APPLET_2_4
  if (panel_applet_get_locked_down (gimlet->applet))
    {
      BonoboUIComponent *popup_component;

      popup_component = panel_applet_get_popup_component (gimlet->applet);

      bonobo_ui_component_set_prop (popup_component,
				    "/commands/Props",
				    "hidden", "1",
				    NULL);
    }
#endif

  place_widgets (gimlet);

  gimlet_language_init (gimlet);

  return;
}

void
gimlet_update_lang (GimletWindow *gimlet)
{
  gtk_widget_queue_draw (gimlet->drawing_area);
}

void
gimlet_status_show_or_hide (GimletWindow *gimlet)
{
  if (gimlet->conversion_mode && gimlet->im_enabled &&
      gimlet->status_enabled &&
      gimlet->status_placement == ON_DESKTOP_PANEL)
    gtk_widget_show (GTK_WIDGET (gimlet->status_label));
  else
    gtk_widget_hide (GTK_WIDGET (gimlet->status_label));
}

void
gimlet_status_set_text (GimletWindow *gimlet, gchar *text)
{
  gtk_label_set_text (GTK_LABEL(gimlet->status_label), text);
  gimlet_status_show_or_hide (gimlet);
}
