/*
 * 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.
 *
 * Authors: Karl Park <karl.park@sun.com>
 */

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#include <stdio.h>
#include <glib.h>
#include <gdk/gdk.h>
#include <gtk/gtk.h>
#include <assert.h>
#include <koinput.h>
#include "pixmap.h"
#include "palette_aux.h"
#include "engine-property.h"
#include "kolelog.h"

extern KOLE_property *p_engine_property;

PaletteInfoRecord palettecore;

GdkColor	_normal_bg;
GdkColor	_normal_text;
GdkColor	_active_bg;
GdkColor	_active_text;
#if 0
GtkWidget *	_full_width_punct_button     = 0;
GtkWidget *	_full_width_letter_button    = 0;
#endif

GtkTooltips *	widget_tooltips                    = 0;

gboolean	_toolbar_window_draging      = FALSE;
gint		_toolbar_window_drag_x       = 0;
gint		_toolbar_window_drag_y       = 0;

gint		_toolbar_window_pos_x 	     = 0;
gint		_toolbar_window_pos_y 	     = 0;

gboolean	_toolbar_window_show_status  = FALSE;
gboolean	_full_width_punct_status     = FALSE;
gboolean	_full_width_letter_status    = FALSE;

static const gchar *
p_active_charsets[] = {
  _("[Wansung]"),
  _("[Johap]"),
  NULL,
};

static const gchar *
p_keyboard_names[] = {
  _("[2bul]"),
  _("[3bul_390]"),
  _("[3bul_final]"),  
  NULL,
};

extern GdkFilterReturn xaux_ext_event_handler(GdkXEvent *gdk_xevent,
					      GdkEvent *event,
					      gpointer user_data);
static GtkWidget *
create_gtk_image_from_xpm (const char **xpm,
			   int          width,
			   int          height,
			   gboolean     force_create);

static void aux_palette_set_inputmode (INPUT_MODE_T i_imode);
static void aux_palette_setup_tooltips ();
static void aux_palette_position_set (gint pos_x, gint pos_y);
static GdkPixbuf * scale_pixbuf (GdkPixbuf *pixbuf,int width, int height);
static void update_input_mode_button (KOLE_property *prop);
static void update_all_widgets (KOLE_property *prop);
static void aux_palette_redraw_self (gboolean visibility);

static gboolean
aux_palette_click_event_handler (GtkWidget *window,
				 GdkEventButton *event,
				 gpointer user_data);

static void aux_palette_input_mode_popup_click_event_handler (gint i);
static void aux_palette_keyboard_popup_click_event_handler (gint i);
static gint aux_palette_input_mode_button_click_event_handler (GtkWidget *widget, GdkEvent *event );
static gint aux_palette_keyboard_button_click_event_handler (GtkWidget *widget, GdkEvent *event);
static GtkWidget *
create_popup_menu_from_list (const gchar **strs, void(*)(gint) );
static void popup_positioner_keyboard (GtkMenu  *menu, gint *x, gint *y,
				       gboolean *push_in, gpointer  func_data);
static void palette_core_data_init (PaletteInfo pinfo);

int main(int argc, char **argv)
{
  PangoFontDescription *font_desc = 0;
  GtkWidget *menu;
  GtkWidget *hbox;
  GtkWidget *frame;
  GtkWidget *image;
  GtkRequisition size;
#if 0
  int dummy = 1;
  while (dummy);
#endif
  
    
  gtk_init (&argc, &argv);
  
  palette_core_data_init (&palettecore);
  
  // Read configurations.
  gdk_color_parse ("gray92",     &_normal_bg);
  gdk_color_parse ("black",      &_normal_text);
  gdk_color_parse ("light blue", &_active_bg);
  gdk_color_parse ("black",      &_active_text);

  palettecore.pdisplay = gdk_display_get_default ();
  palettecore.pscreen = gdk_display_get_default_screen (palettecore.pdisplay);
  
  font_desc = pango_font_description_from_string ("sans 10");
  
  //Create toolbar window
  palettecore.ppalette = gtk_window_new (GTK_WINDOW_POPUP);
  gtk_window_set_policy (GTK_WINDOW (palettecore.ppalette),
			 TRUE, TRUE, FALSE);
  gtk_window_set_resizable (GTK_WINDOW (palettecore.ppalette), FALSE);
  gtk_widget_add_events (palettecore.ppalette, GDK_BUTTON_PRESS_MASK);
  gtk_widget_add_events (palettecore.ppalette, GDK_BUTTON_RELEASE_MASK);
  gtk_widget_add_events (palettecore.ppalette, GDK_POINTER_MOTION_MASK);
  g_signal_connect (G_OBJECT (palettecore.ppalette),
		    "button-press-event",
		    G_CALLBACK (aux_palette_click_event_handler),
		    GINT_TO_POINTER (0));
  g_signal_connect (G_OBJECT (palettecore.ppalette),
		    "button-release-event",
		    G_CALLBACK (aux_palette_click_event_handler),
		    GINT_TO_POINTER (1));

  frame = gtk_frame_new (0);
    
  gtk_frame_set_shadow_type (GTK_FRAME (frame), GTK_SHADOW_OUT);
  gtk_container_add (GTK_CONTAINER (palettecore.ppalette), frame);

  hbox = gtk_hbox_new (FALSE, 0);
  gtk_container_add (GTK_CONTAINER (frame), hbox);

  image = create_gtk_image_from_xpm ((const char **)move_xpm, 24, 20, 1);
  gtk_box_pack_start (GTK_BOX (hbox), image, FALSE, FALSE, 0);

  palettecore.ppopup_input_mode =
    create_popup_menu_from_list (p_active_charsets, aux_palette_input_mode_popup_click_event_handler);

  palettecore.pbutton_input_mode = gtk_button_new ();
  gtk_widget_modify_font (GTK_BIN (palettecore.pbutton_input_mode)->child,
			  font_desc);
  gtk_button_set_relief (GTK_BUTTON (palettecore.pbutton_input_mode),
			 GTK_RELIEF_NONE);
  gtk_box_pack_start (GTK_BOX (hbox), palettecore.pbutton_input_mode,
		      TRUE, TRUE, 0);
  g_signal_connect_swapped (G_OBJECT (palettecore.pbutton_input_mode),
			    "button_press_event",
			    G_CALLBACK (aux_palette_input_mode_button_click_event_handler),
			    menu);

  //New full_width_punctuation button
  image = create_gtk_image_from_xpm ((const char **)keyboard_xpm, -1, -1, 1);
  gtk_widget_size_request (image, &size);
  palettecore.pbutton_keyboard = gtk_button_new ();
  gtk_button_set_relief (GTK_BUTTON (palettecore.pbutton_keyboard),
			 GTK_RELIEF_NONE);
  gtk_container_add (GTK_CONTAINER (palettecore.pbutton_keyboard), image);
  gtk_widget_set_size_request (palettecore.pbutton_keyboard,
			       size.width + 4, size.height + 3);
  gtk_box_pack_start (GTK_BOX (hbox),
		      palettecore.pbutton_keyboard,
		      TRUE, TRUE, 0);

  g_signal_connect (G_OBJECT (palettecore.pbutton_keyboard),
		    "button_press_event",
		    G_CALLBACK (aux_palette_keyboard_button_click_event_handler),
		    0);

  /*  
  g_signal_connect_swapped (G_OBJECT (palettecore.pbutton_keyboard),
			    "button_press_event",
			    G_CALLBACK (aux_palette_keyboard_button_click_event_handler),
			    menu);
  */
  palettecore.ppopup_keyboard =
    create_popup_menu_from_list (p_keyboard_names,
				 aux_palette_keyboard_popup_click_event_handler);
    
  //New full_width_punctuation button
  image = create_gtk_image_from_xpm ((const char **)options_xpm, -1, -1, 1);
  gtk_widget_size_request (image, &size);
  palettecore.pbutton_option = gtk_button_new ();
  gtk_button_set_relief (GTK_BUTTON (palettecore.pbutton_option),
			 GTK_RELIEF_NONE);
  gtk_container_add (GTK_CONTAINER (palettecore.pbutton_option), image);
  gtk_widget_set_size_request (palettecore.pbutton_option,
			       size.width + 4, size.height + 3);
  gtk_box_pack_start (GTK_BOX (hbox),
		      palettecore.pbutton_option,
		      TRUE, TRUE, 0);
  gtk_widget_show_all (palettecore.ppalette);

    
  _toolbar_window_show_status = TRUE;

  gtk_widget_size_request (palettecore.ppalette, &size);
  aux_palette_position_set (gdk_screen_width () - size.width - 16, 
			    gdk_screen_height () - size.height -16);

  gtk_widget_hide(palettecore.ppalette);


  gdk_window_add_filter(palettecore.ppalette->window,
			xaux_ext_event_handler, 0);
  xaux_ext_register_classes(palettecore.ppalette->window);

  aux_palette_setup_tooltips ();
  gtk_main ();
  if (font_desc)
    pango_font_description_free (font_desc);
}


static GtkWidget *
create_gtk_image_from_xpm (const char **xpm,
                         int          width,
                         int          height,
                         gboolean     force_create)
{
  GtkWidget *icon;
  GdkPixbuf *pixbuf = gdk_pixbuf_new_from_xpm_data (xpm);
  

  if (!pixbuf && !force_create)
    return 0;
  
  if (!pixbuf) {
    if (width <= 0 || height <= 0)
      return 0;
    
    pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
    
    if (!pixbuf)
      return 0;
    
    gdk_pixbuf_fill (pixbuf, 0);
  }

  if (width <= 0)
    width = gdk_pixbuf_get_width (pixbuf);
  if (height <= 0)
    height = gdk_pixbuf_get_height (pixbuf);

  pixbuf = scale_pixbuf (pixbuf, width, height);

  icon = gtk_image_new_from_pixbuf (pixbuf);
  gtk_widget_show (icon);

  gdk_pixbuf_unref (pixbuf);

  return icon;
}

static void
aux_palette_position_set (gint pos_x, gint pos_y)
{
  GtkRequisition ws;
  /*
   */
  gtk_widget_size_request (palettecore.ppalette, &ws);
    
  if (pos_x + ws.width > gdk_screen_width ()) {
    pos_x = gdk_screen_width () - ws.width;
  } else if (pos_x < 0) {
    pos_x = 0;
  }
  if (pos_y + ws.height > gdk_screen_height ())
    pos_y = gdk_screen_height () - ws.height;
  else if (pos_y < 0)
    pos_y = 0;
    
  if (_toolbar_window_pos_x != pos_x || _toolbar_window_pos_y != pos_y) {
    gtk_window_move (GTK_WINDOW (palettecore.ppalette), pos_x, pos_y);
    _toolbar_window_pos_x = pos_x;
    _toolbar_window_pos_y = pos_y;
  }
  /*
    gtk_window_move (GTK_WINDOW (palettecore.ppalette), pos_x, pos_y);
  */
}

static void
gtk_item_factory_menu_pos (GtkMenu  *menu,
                           gint     *x,
                           gint     *y,
                           gboolean *push_in,
                           gpointer  func_data)
{
  GdkEventButton *bevent = (GdkEventButton *)func_data;
  GtkRequisition size_menu, size_widget;
  gint menu_pos_x, menu_pos_y;

  gtk_widget_size_request ((GtkWidget *)menu, &size_menu);

  if (_toolbar_window_pos_y - size_menu.height > 0) {
    menu_pos_y = _toolbar_window_pos_y - size_menu.height;
  } else {
    gtk_widget_size_request ((GtkWidget *)palettecore.ppalette, &size_widget);
    menu_pos_y = _toolbar_window_pos_y + size_widget.height;
  }

  menu_pos_x = _toolbar_window_pos_x + palettecore.pbutton_input_mode->allocation.x;

  *x = menu_pos_x;
  *y = menu_pos_y;
}

static void
popup_positioner_keyboard (GtkMenu  *menu,
                           gint     *x,
                           gint     *y,
                           gboolean *push_in,
                           gpointer  func_data)
{
  GdkEventButton *bevent = (GdkEventButton *)func_data;
  GtkRequisition size_menu, size_widget;
  gint menu_pos_x, menu_pos_y;

  gtk_widget_size_request ((GtkWidget *)menu, &size_menu);

  if (_toolbar_window_pos_y - size_menu.height > 0) {
    menu_pos_y = _toolbar_window_pos_y - size_menu.height;
  } else {
    gtk_widget_size_request ((GtkWidget *)palettecore.ppalette, &size_widget);
    menu_pos_y = _toolbar_window_pos_y + size_widget.height;
  }

  menu_pos_x = _toolbar_window_pos_x + palettecore.pbutton_input_mode->allocation.x;

  *x = menu_pos_x;
  *y = menu_pos_y;
}

static gint
aux_palette_input_mode_button_click_event_handler (GtkWidget *widget,
			   GdkEvent *event )
{
  GtkWidget *pp;
  pp = palettecore.ppopup_input_mode; 
  if (pp == 0)
    return TRUE;

  if (event->type == GDK_BUTTON_PRESS) {
    GdkEventButton *bevent = (GdkEventButton *) event;

    KOLE_LOG (LOGDEST_STDOUT, "Input status button popup menu");
    gtk_menu_popup (GTK_MENU (pp), NULL, NULL, 
		    gtk_item_factory_menu_pos, bevent,
		    bevent->button, bevent->time);
    /* Tell calling code that we have handled this event; the buck
     * stops here. */
    return TRUE;
  }

  /* Tell calling code that we have not handled this event; pass it on. */
  return FALSE;
}

static void
aux_palette_input_mode_popup_click_event_handler (gint i)
{
  gchar **p = (gchar **) p_active_charsets;
  KOLE_LOG (LOGDEST_STDOUT, "%s selected", p_active_charsets[i]);
  
  if (i != leproperty_get_charset (p_engine_property)){
    leproperty_set_charset (p_engine_property, i);
    paletteaux_send_switch_charset_request (i);
  }
  update_all_widgets (p_engine_property);
}

static void
aux_palette_keyboard_popup_click_event_handler (gint i)
{
#if 0
  gchar **p = (gchar **) p_active_charsets;
  KOLE_LOG (LOGDEST_STDOUT, "%s selected", p_active_charsets[i]);
  
  if (i != leproperty_get_charset (p_engine_property)){
    leproperty_set_charset (p_engine_property, i);
    paletteaux_send_switch_charset_request (i);
  }
  update_all_widgets (p_engine_property);
#endif
  KOLE_LOG (LOGDEST_STDOUT, "%s chosen", p_keyboard_names [i]);
  paletteaux_send_show_keyboardaux_request (i);
}

static GtkWidget *
create_popup_menu_from_list (const gchar **strs,
			     void (*popup_menu_handler) (gint) )
{
  GtkWidget *menu;
  GtkWidget *menuitem;
  char **p;
  int i;

  menu = gtk_menu_new();

  for (p=strs, i = 0; *p; p++, i++) {
    menuitem = gtk_menu_item_new_with_label(*p);
    gtk_menu_shell_append (GTK_MENU_SHELL(menu), menuitem);
    g_signal_connect_swapped(G_OBJECT(menuitem), "activate",
			     G_CALLBACK(popup_menu_handler), (gpointer )i);
    gtk_widget_show(menuitem);
  }

  gtk_widget_show(menu);

  return(menu);
}
#if 0
static gint
ui_full_width_punct_button_click_cb (GtkWidget *widget,
				     GdkEvent *event )
{
  gboolean full_width_punct_status = !_full_width_punct_status;

  ui_toggle_punct (full_width_punct_status);
}

static gint
ui_full_width_letter_button_click_cb (GtkWidget *widget,
				      GdkEvent *event)
{
  gboolean full_width_letter_status = !_full_width_letter_status;

  ui_toggle_letter(full_width_letter_status);
}
#endif

static gint
aux_palette_keyboard_button_click_event_handler (GtkWidget *widget,
						 GdkEvent *event)
{
  GdkEventButton *bev;
  
  if (palettecore.pbutton_keyboard == 0)
    return ;
  
  if (event->type == GDK_BUTTON_PRESS){
    bev = (GdkEventButton *) event;

    KOLE_LOG (LOGDEST_STDOUT, "Virtual Keyboard button popup menu");
    gtk_menu_popup (GTK_MENU (palettecore.ppopup_keyboard),
		    NULL, NULL,
		    popup_positioner_keyboard, bev,
		    bev->button, bev->time);
    return True;
  }
  
}

static gboolean
ui_toolbar_window_motion_cb (GtkWidget *window,
                             GdkEventMotion *event,
                             gpointer user_data)
{
  gint pos_x, pos_y;
  guint state = GDK_BUTTON1_MASK | GDK_BUTTON2_MASK | GDK_BUTTON3_MASK;
  
  if ((event->state & state) != 0 && _toolbar_window_draging) {
    
    gtk_window_get_position (GTK_WINDOW (window), &pos_x, &pos_y);
    aux_palette_position_set (
			      pos_x + ((gint) event->x_root - _toolbar_window_drag_x),
			      pos_y + ((gint) event->y_root - _toolbar_window_drag_y));

    _toolbar_window_drag_x = (gint) event->x_root;
    _toolbar_window_drag_y = (gint) event->y_root;
                                                                                                          
    return TRUE;
  }
  return FALSE;
}

static gboolean
aux_palette_click_event_handler (GtkWidget *window,
                            GdkEventButton *event,
                            gpointer user_data)
{
  int click_type = GPOINTER_TO_INT (user_data);
  static gulong motion_handler;
  GdkCursor *cursor;
  if (click_type == 0 && event->button <= 1) {
    if (_toolbar_window_draging)
      return FALSE;
    // Connection pointer motion handler to this window.
    motion_handler =
      g_signal_connect (G_OBJECT (window), "motion-notify-event",
			G_CALLBACK (ui_toolbar_window_motion_cb),
			NULL);


    _toolbar_window_draging = TRUE;
    _toolbar_window_drag_x = (gint) event->x_root;
    _toolbar_window_drag_y = (gint) event->y_root;
    cursor = gdk_cursor_new (GDK_TOP_LEFT_ARROW);

    // Grab the cursor to prevent losing events.
    gdk_pointer_grab (window->window, TRUE,
		      (GdkEventMask) (GDK_BUTTON_RELEASE_MASK | GDK_POINTER_MOTION_MASK),
		      NULL, cursor, event->time);
    gdk_cursor_unref (cursor);
    return TRUE;
  } else if (click_type == 1 && event->button <= 1) {
    if (!_toolbar_window_draging)
      return FALSE;
    g_signal_handler_disconnect (G_OBJECT (window), motion_handler);
    gdk_pointer_ungrab (event->time);
    _toolbar_window_draging = FALSE;

    return TRUE;
  } else if (click_type == 1 && event->button > 1) {
    return TRUE;
  }
  return FALSE;
}



static GdkPixbuf *
scale_pixbuf (GdkPixbuf *pixbuf, int        width, int        height)
{
  if (pixbuf) {
    if (gdk_pixbuf_get_width (pixbuf) != width ||
	gdk_pixbuf_get_height (pixbuf) != height) {
      GdkPixbuf *dest =
	gdk_pixbuf_scale_simple (pixbuf, width, height, GDK_INTERP_BILINEAR);
      gdk_pixbuf_unref (pixbuf);
      pixbuf = dest;
        
    }
  }
  return pixbuf;
}

static void
aux_palette_setup_tooltips ()
{

  palettecore.ptooltip = gtk_tooltips_new ();
  gtk_tooltips_set_delay (palettecore.ptooltip, 1000);
  gtk_tooltips_set_tip (palettecore.ptooltip,
			palettecore.pbutton_input_mode,
			_("Click to move the toolbar"),
			NULL);
  gtk_tooltips_set_tip (palettecore.ptooltip,
			palettecore.pbutton_keyboard,
			_("Click to switch to use other keyboard layout"),
			NULL);
  gtk_tooltips_set_tip (palettecore.ptooltip,
			palettecore.pbutton_keyboard,
			_("Click to switch to use other keyboard layout"),
			NULL);
  gtk_tooltips_set_tip (palettecore.ptooltip,
			palettecore.pbutton_option,
			_("Click to start option auxiliary window"),
			NULL);
}

static void
aux_palette_set_inputmode (INPUT_MODE_T i_mode)
{
  if (i_mode > INPUT_MODE_NONE && i_mode <= INPUT_MODE_SYMBOL)
    leproperty_set_input_mode (p_engine_property, i_mode);
  else
    leproperty_set_input_mode (p_engine_property, INPUT_MODE_NONE);
  
  update_input_mode_button (p_engine_property);
}

static void
aux_palette_redraw_self (gboolean visibility)
{
  if (visibility)
    gtk_widget_show_all (palettecore.ppalette);
  else
    gtk_widget_hide (palettecore.ppalette);
}

static void
update_all_widgets (KOLE_property *prop)
{
  update_input_mode_button (prop);
}

static void
update_input_mode_button (KOLE_property *prop)
{
  int i;
  assert (prop != NULL);
  i = leproperty_get_charset (prop);
  gtk_button_set_label (GTK_BUTTON (palettecore.pbutton_input_mode), p_active_charsets[i]);
}

static void
palette_core_data_init (PaletteInfo pinfo)
{
  assert (pinfo != NULL);
  pinfo->ppalette = NULL;
  pinfo->pbutton_input_mode = NULL;
  pinfo->ppopup_input_mode = NULL;
  pinfo->pbutton_keyboard = NULL;
  pinfo->pbutton_option = NULL;
  pinfo->ptooltip = NULL;
}

void
paletteaux_update_display (KOLE_property *pep)
{
  update_all_widgets (pep);
}

void
paletteaux_change_visibility (gboolean visibility)
{
  if (visibility == FALSE)
    gtk_widget_hide (palettecore.ppalette);
  else
    gtk_widget_show_all (palettecore.ppalette);
}

static GtkWidget *
ui_create_punct_icon (gboolean full_width_punct_status)
{
  GtkWidget *image;
  const char **xpm;

  if (full_width_punct_status == TRUE)
    xpm = (const char **)fullwidth_xpm;
  else
    xpm = (const char **)halfwidth_xpm;

  image = create_gtk_image_from_xpm(xpm, -1, -1, 1);
  return(image);
}

static GtkWidget *
ui_create_letter_icon(gboolean full_width_letter_status)
{
  GtkWidget *image;
  const char **xpm;

  if (full_width_letter_status == TRUE)
    xpm = (const char **)ch_punct_xpm;
  else
    xpm = (const char **)en_punct_xpm;

  image = create_gtk_image_from_xpm(xpm, -1, -1, 1);
  return(image);
}

#if 0
static void
ui_toggle_punct(gboolean full_width_punct_status)
{
  if (_full_width_punct_status == full_width_punct_status)
    return;

  _full_width_punct_status = full_width_punct_status;

  GtkWidget *image;

  image = gtk_bin_get_child (GTK_BIN (_full_width_punct_button));
  gtk_container_remove (GTK_CONTAINER (_full_width_punct_button), image);

  image = ui_create_punct_icon (_full_width_punct_status);
  gtk_container_add (GTK_CONTAINER (_full_width_punct_button), image);

  if (_toolbar_window_show_status)
    gtk_widget_show (_full_width_punct_button);
}

void
ui_toggle_letter (gboolean full_width_letter_status)
{
  GtkWidget *image;
  if (_full_width_letter_status == full_width_letter_status)
    return;

  _full_width_letter_status = full_width_letter_status;


  image = gtk_bin_get_child (GTK_BIN (_full_width_letter_button));
  gtk_container_remove (GTK_CONTAINER (_full_width_letter_button), image);

  image = ui_create_letter_icon (_full_width_letter_status);
  gtk_container_add (GTK_CONTAINER (_full_width_letter_button), image);

  if (_toolbar_window_show_status)
    gtk_widget_show (_full_width_letter_button);
}
#endif
