/* 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/gtksignal.h>
#include <panel-applet.h>
#include <gnome.h>
#include <gtk/gtkdialog.h>
#include <gtk/gtkradiomenuitem.h>

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

static void
get_menu_pos (GtkMenu *menu, gint *x, gint *y, gboolean *push_in, gpointer data)
{
  GimletWindow *curr_data = data;
  GtkRequisition  reqmenu;
  gint tempx, tempy, width, height;
  gint screen_width, screen_height;
	
  gtk_widget_size_request (GTK_WIDGET (menu), &reqmenu);
  gdk_window_get_origin (GTK_WIDGET (curr_data->applet)->window, &tempx, &tempy);
  gdk_window_get_geometry (GTK_WIDGET (curr_data->applet)->window, NULL, NULL,
			   &width, &height, NULL);
     			      
  switch (panel_applet_get_orient (PANEL_APPLET (curr_data->applet))) {
  case PANEL_APPLET_ORIENT_DOWN:
    tempy += height;
    break;
  case PANEL_APPLET_ORIENT_UP:
    tempy -= reqmenu.height;
    break;
  case PANEL_APPLET_ORIENT_LEFT:
    tempx -= reqmenu.width;
    break;
  case PANEL_APPLET_ORIENT_RIGHT:
    tempx += width;
    break;
  }
  screen_width = gdk_screen_width ();
  screen_height = gdk_screen_height ();
  *x = CLAMP (tempx, 0, MAX (0, screen_width - reqmenu.width));
  *y = CLAMP (tempy, 0, MAX (0, screen_height - reqmenu.height));
}

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

static void
update_langmenu_cb (GtkWidget *menuitem, GimletWindow *gimlet)
{
  GtkWindow *transient_parent;
  GtkWindow *old_transient_parent;

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

static void
activate_cb (GtkWidget *menuitem, GimletWindow *gimlet)
{
  if (GTK_MENU_ITEM (menuitem))
    {
      gchar *iiim_lang;
      gchar *lename, *lang_le;
      gchar *conversion_mode;

      iiim_lang = g_strdup(g_object_get_data (G_OBJECT (menuitem), "iiim-lang-name"));
      lename = g_strdup(gtk_label_get_text (GTK_LABEL (GTK_BIN (menuitem)->child)));
      lang_le = g_strconcat(iiim_lang, ":", lename, NULL);

      gimlet_iiim_language_set (gimlet, lang_le);

      free(lang_le);

      if (gimlet->current_iiim_lang)
	g_free (gimlet->current_iiim_lang);
      gimlet->current_iiim_lang = g_strdup (iiim_lang);

      gimlet_update_lang (gimlet);

      /* set initial conversion mode */
      if (gimlet->conversion_on_start == FALSE)
	conversion_mode = "off";
      else
	conversion_mode = gimlet_language_get_conversion_mode (iiim_lang);

      gimlet_iiim_conversion_mode_set (gimlet, conversion_mode);
    }
}

static void
turn_off_cb (GtkWidget *menuitem, GimletWindow *gimlet)
{
  gimlet_iiim_conversion_mode_set (gimlet, "off");
}

static
gint string_comp(gconstpointer a, gconstpointer b)
{
  return g_strcasecmp (a, b);
}

GSList*
get_iiimf_lang_le_list (GimletWindow *gimlet, gchar *iiim_lang_name)
{
  const gchar *im_delimiter = ";";
  gchar **input_method_list = NULL;
  GSList *lelist = NULL;

  if (gimlet->le_list == NULL)
    return NULL;

  input_method_list = g_strsplit (gimlet->le_list, im_delimiter, -1);

  if (input_method_list)
    {
      gchar **p;
      const gchar *le_delimiter = ":";
      gchar **le = NULL;

      for (p = input_method_list; *p; p++)
	{
	  le = g_strsplit (*p, le_delimiter, -1);
	  if ((strcmp ((gchar*)le[0], iiim_lang_name) == 0) &&
	      !(g_slist_find_custom (lelist, le[1], (GCompareFunc)string_comp)))
	      lelist = g_slist_append (lelist, le[1]);
	}
    }
  g_strfreev (input_method_list);
  return lelist;
}

static void
quick_lang_menu_init (GimletWindow *gimlet)
{
  GtkWidget *menu;
  GtkWidget *menuitem;
  GSList *active_languages;
  GSList *tmp;
  gchar key_navi[2];
  /*
    Added underlined access keys 'A' - 'Y' for all the language items on the
    language menu for key navigation. 'Z' is used for Add or Remove...
  */
  menu = gtk_menu_new ();
  active_languages = gimlet_language_get_active_languages ();

  key_navi[0] = 'A';
  key_navi[1] = '\0';

  for (tmp = active_languages; tmp; tmp = g_slist_next (tmp))
    {
      char *name;
      char *mnemonic_label;
      char *iiim_lang_name;
      name = gimlet_language_get_name (tmp->data);
      if (strcmp (name, "ASCII") == 0)
	continue;
      iiim_lang_name = gimlet_language_get_iiim_lang_name (tmp->data);
      /* add keynav */
      mnemonic_label = g_strconcat (name, "(_", key_navi, ")", NULL);
      menuitem = gtk_menu_item_new_with_mnemonic (mnemonic_label);
      g_free (mnemonic_label);
      if (key_navi[0] == 'Y')
	key_navi[0] = 'A';
      else
	key_navi[0] += 1;

      GSList *lelist = get_iiimf_lang_le_list (gimlet, iiim_lang_name);
      int len = g_slist_length (lelist);
      if (len > 1)
	{
	  GtkWidget *le_submenu;
	  GtkWidget *le_submenu_item;

	  le_submenu = gtk_menu_new ();

	  GSList *le;
	  for (le = lelist; le; le = g_slist_next (le))
	    {
	      le_submenu_item = gtk_menu_item_new_with_label (le->data);
	      g_object_set_data (G_OBJECT (le_submenu_item), "iiim-lang-name",
				 iiim_lang_name);
	      g_object_set_data (G_OBJECT (le_submenu_item), "iiim-display-name",
				 name);
	      gtk_menu_shell_append (GTK_MENU_SHELL (le_submenu), le_submenu_item);
	      g_signal_connect (le_submenu_item, "activate",
				G_CALLBACK (activate_cb), gimlet);
	      gtk_widget_show (le_submenu_item);
	    }
	  gtk_menu_item_set_submenu (GTK_MENU_ITEM (menuitem), le_submenu);
	  gtk_widget_show (le_submenu);
	}
      else if (len == 1)
	{
	  g_object_set_data (G_OBJECT (menuitem), "iiim-lang-name",
			     iiim_lang_name);
	  g_object_set_data (G_OBJECT (menuitem), "iiim-display-name",
			     name);
	  g_signal_connect (GTK_MENU_ITEM (menuitem), "activate",
			    G_CALLBACK (activate_cb), gimlet);
	}

      g_slist_free (lelist);

      gtk_widget_show (menuitem);
      gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);

    }

  /* add separator */
  menuitem = gtk_separator_menu_item_new ();
  gtk_widget_show (menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL (menu), menuitem);

  /* off item */
  char *name;
  char *mnemonic_label;
  char *iiim_lang_name;
  name = gimlet_language_get_name (active_languages->data);
  iiim_lang_name = gimlet_language_get_iiim_lang_name (active_languages->data);
  mnemonic_label = g_strconcat (_(name), "(_0)", NULL);
  menuitem = gtk_menu_item_new_with_mnemonic (mnemonic_label);
  gtk_widget_show (menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
  g_object_set_data (G_OBJECT (menuitem), "iiim-lang-name",
		     iiim_lang_name);
  g_object_set_data (G_OBJECT (menuitem), "iiim-display-name",
		     name);
  g_signal_connect (menuitem, "activate",
		    G_CALLBACK (turn_off_cb), gimlet);

  menuitem = gtk_menu_item_new_with_mnemonic (_("Add or Remove...(_Z)"));
  gtk_widget_show (menuitem);
  gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
  g_signal_connect (menuitem, "activate",
		    G_CALLBACK (update_langmenu_cb), gimlet);

  gimlet->quick_access_menu->widget = menu;
  gimlet->quick_access_menu->active_languages = active_languages;
  
  return;
}

void
quick_access_menu_destroy (GimletWindow *gimlet)
{
  if (gimlet->quick_access_menu->widget)
    {
      gtk_widget_destroy (gimlet->quick_access_menu->widget);
      gimlet->quick_access_menu->widget = NULL;
    }
  if (gimlet->quick_access_menu->active_languages)
    {
      g_slist_foreach (gimlet->quick_access_menu->active_languages,
		       (GFunc) gimlet_language_free,
		       NULL);
      g_slist_free (gimlet->quick_access_menu->active_languages);
      gimlet->quick_access_menu->active_languages = NULL;
    }
}


/* public */
void
gimlet_quick_access_menu_init (GimletWindow *gimlet)
{
  if (gimlet->quick_access_menu == NULL)
    gimlet->quick_access_menu = g_new0 (QuickAccessMenu, 1);

  quick_access_menu_destroy (gimlet);
  quick_lang_menu_init (gimlet);
}

void
gimlet_quick_access_menu_show (GimletWindow *gimlet)
{
  gimlet_quick_access_menu_init (gimlet);
  gtk_menu_popup (GTK_MENU (gimlet->quick_access_menu->widget), NULL, NULL,
		  get_menu_pos, gimlet,
		  0, 0);
  return;
}
void
gimlet_quick_access_menu_hide (GimletWindow *gimlet)
{
  quick_access_menu_destroy (gimlet);

  if (gimlet->quick_access_menu)
    g_free (gimlet->quick_access_menu);
  gimlet->quick_access_menu = NULL;
}
