#include <stdio.h>
#include <gdk/gdkx.h>
#include <gtk/gtk.h>
#include <signal.h>
#include <wait.h>

#include "palette_messages.h"
#include "palette_aux.h"
#include "vkb_aux.h"

extern palette_window_t *palette_window;

void palette_window_signal_child_handler(int sig, siginfo_t * info,
				  void *ucontext);

void palette_window_change_current_ime(ime_module_t *ime_module,
				       gboolean bNeedNotifyLE)
{
    if (ime_module == NULL)
	return;

    if (bNeedNotifyLE) {
	palette_aux_Switch_LE_Engine_Request((char *)ime_module->uuid);
	return;
    }

    palette_window->current_ime = ime_module;
    palette_window_update_layout(palette_window);
}

static void
palette_window_ime_menuitem_cb(GtkWidget *menuitem,
			       gpointer data)
{
    ime_module_t *ime_module = (ime_module_t *)data;

    if (ime_module == NULL)
	return;

    ime_module_print(ime_module);

    palette_window_change_current_ime(ime_module, TRUE);
    return;
}

static gboolean
palette_window_menu_button_release_cb(GtkWidget *menu,
				      GdkEventButton *event,
				      gpointer data)
{
    palette_window_t *palette_window = (palette_window_t *)data;
    int x, y;

    DEBUG_printf("palette_window_ime_menu_button_release_cb ====\n");

    if (palette_window == NULL)
	return FALSE;

    gdk_window_get_pointer (palette_window->window->window, &x, &y, NULL);
    palette_window->focused_button = (palette_button_t *)
				     palette_window_get_button_from_pos(palette_window, x, y);

    palette_window->pressed_button = NULL;
    palette_window_draw_layout(palette_window);

    palette_window->menu_popuped = 0;

    return FALSE;
}

GtkWidget *palette_window_create_ime_list_menu(palette_window_t *palette_window,
					       property_data_t *property_data)
{
    GtkWidget *menu; 
    GtkWidget *menu_item;

    char buf[256];
    gint width, height;

    int i;

    if (property_data == NULL)
	return NULL;

/*
    property_data_print(property_data);
*/

    gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &width, &height);
    DEBUG_printf("icon: width: %d, height: %d\n", width, height);

    /* create icon for each ime entry */
    for (i = 0; i < property_data->num_ime_modules; i++) {
	char icon_path[256];
	ime_module_t *ime_module = property_data->ime_modules[i];

	if (ime_module == NULL)
	    continue;

	if (ime_module->icon_pixbuf == NULL && ime_module->icon_file != NULL) {
	    if (ime_module->icon_file[0] == '/')
		snprintf(icon_path, 256, "%s", ime_module->icon_file);
	    else
		snprintf(icon_path, 256, "%s/icons/%s",
			 LE_IME_MODULES_DIR, ime_module->icon_file);

            ime_module->icon_pixbuf = (GdkPixbuf *)palette_window_new_pixbuf_from_xpm(
								     icon_path,
								     NULL,
								     width,
								     height,
								     FALSE);
	}
	if (ime_module->icon_pixbuf == NULL && palette_window->pixbufs[PIXMAP_ID_DEFAULT_IME])
	    ime_module->icon_pixbuf = gdk_pixbuf_copy(
				palette_window->pixbufs[PIXMAP_ID_DEFAULT_IME]);
    }

    menu = gtk_menu_new();
    for (i = 0; i < property_data->num_ime_modules; i++) {
	GtkWidget *icon_widget;
	ime_module_t *ime_module = property_data->ime_modules[i];

	if (ime_module == NULL)
	    continue;

	if (ime_module->enabled == 0)
	    continue;

        snprintf(buf, 256, "%s", (char *)ime_module->name);

        menu_item = gtk_image_menu_item_new_with_label(buf);
	if (ime_module->icon_pixbuf) {
	    icon_widget = gtk_image_new_from_pixbuf(ime_module->icon_pixbuf);
	    if (icon_widget != NULL)
		gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
					      icon_widget);
	}
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
        g_signal_connect(G_OBJECT(menu_item),
			 "activate",
                         G_CALLBACK(palette_window_ime_menuitem_cb),
			 (gpointer) ime_module);
        gtk_widget_show(menu_item);
    }

    gtk_widget_show(menu);

    g_signal_connect(G_OBJECT (menu),
                     "button_release_event",
                     G_CALLBACK (palette_window_menu_button_release_cb),
                     (gpointer)palette_window);

    g_object_set_data(G_OBJECT(menu),
		      DATA_PALETTE_AUX_WINDOW_INFO,
		      (gpointer)palette_window);

    return menu;
}

static void palette_vkb_menu_item_cb(gpointer data)
{
    vkb_layout_t *vkb_layout = (vkb_layout_t *)data;

    palette_window->current_vkb_layout = vkb_layout;
    palette_window_show_vkb_window_with_layout(palette_window, vkb_layout);
    return;
}

GtkWidget *palette_window_create_vkb_list_menu(palette_window_t *palette_window)
{
    GtkWidget *menu; 
    GtkWidget *menu_item;
    GSList    *group = NULL;

    gboolean tearoff = FALSE;

    char buf[256];
    vkb_layout_t **p, **vkb_layout_list;

    vkb_layout_list = (vkb_layout_t **)palette_window_get_vkb_layout_list(palette_window);
    if (vkb_layout_list == NULL)
	return NULL;

    menu = gtk_menu_new();

    if (tearoff) {
        menu_item = gtk_tearoff_menu_item_new ();
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
        gtk_widget_show (menu_item);
    }

    for (p = vkb_layout_list; *p; p++) {
	vkb_layout_t *vkb_layout = *p;
        snprintf(buf, 256, " %s ", (char *)vkb_layout->name_utf8);

        menu_item = gtk_radio_menu_item_new_with_label(group, buf);
	group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (menu_item));
        gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
        g_signal_connect_swapped(G_OBJECT(menu_item), "activate",
                                 G_CALLBACK(palette_vkb_menu_item_cb), (gpointer) vkb_layout);
        gtk_widget_show(menu_item);
    }

    gtk_widget_show(menu);

    g_signal_connect(G_OBJECT (menu),
                     "button_release_event",
                     G_CALLBACK (palette_window_menu_button_release_cb),
                     (gpointer)palette_window);

    g_object_set_data(G_OBJECT(menu),
		      DATA_PALETTE_AUX_WINDOW_INFO,
		      (gpointer)palette_window);

    return menu;
}

void palette_window_register_signal_child_handler()
{
    struct sigaction act;

    act.sa_handler = NULL;
    act.sa_sigaction = palette_window_signal_child_handler;
    sigfillset(&act.sa_mask);
    act.sa_flags = SA_SIGINFO;

    sigaction(SIGCHLD, &act, NULL);
}

void
palette_window_signal_child_handler(int sig, siginfo_t * info, void *ucontext)
{
    pid_t pid;
    int status;

    while ((pid = waitpid(info->si_pid, &status, WNOHANG | WUNTRACED)) > 0) {
	printf("pid %d: die\n", pid);
    }
}

static void palette_window_start_command(char *command_str)
{
    int pid;

    if (command_str == NULL)
	return;

    palette_window_register_signal_child_handler();

    pid = fork();
    if (pid < 0) {
	return;
    } else if (pid == 0) {
	/* in child process */
	execl("/bin/sh", "sh", "-c", command_str, (char *) 0);

	/* Exec failed. */
	fprintf(stderr, "Error: Could not exec %s!\n", command_str);
	_exit(1);
    }
    return;
}

static void
palette_window_start_uni_charmap_app(GtkWidget   *menuitem,
				     palette_window_t *palette_window)
{
    palette_window_start_command("/usr/bin/gucharmap");
}

static void
palette_window_toggled_show_style_cb(GtkWidget   *menuitem,
				    palette_window_t *palette_window)
{
    if (palette_window->show_style == SHOW_STYLE_HORIZONTAL) {
        palette_window_set_show_style(palette_window, SHOW_STYLE_VERTICAL);
        if (palette_window->property_data != NULL)
	    palette_window->property_data->show_with_vertical = 1;
    } else {
        palette_window_set_show_style(palette_window, SHOW_STYLE_HORIZONTAL);
        if (palette_window->property_data != NULL)
	    palette_window->property_data->show_with_vertical = 0;
    }
    if (palette_window->property_window != NULL)
        palette_window->property_window->modified_status = TRUE;
}

static void
palette_window_start_toolbar_perferences_app(GtkWidget   *menuitem,
					     palette_window_t *palette_window)
{
}

static void
palette_window_start_ime_properties_app(GtkWidget   *menuitem,
				        palette_window_t *palette_window)
{
    if (palette_window == NULL)
	return;

    if (palette_window->property_window == NULL) {
	palette_window->property_window = (property_window_t *)property_window_new_with_property_data(palette_window->property_data);
    }

    if (palette_window->property_window != NULL) {
	property_window_restore(palette_window->property_window);
        property_window_show(palette_window->property_window);
    }
}

static void
palette_window_start_ime_help_app(GtkWidget   *menuitem,
				  palette_window_t *palette_window)
{
#ifndef STANDALONE_DEBUG
    char command_str[256];

    snprintf(command_str, 256, "/usr/bin/mozilla %s/index_jds.html", LE_DOCS_DIR);
    palette_window_start_command(command_str);
#else
    g_signal_emit_by_name(palette_window->window, "destroy");
    exit (0);
#endif
}

static void
palette_window_destroy_ime_about_dialog(GtkDialog *dialog, int response_id, gpointer data)
{
    palette_window_t *platte_window = (palette_window_t *)data;

    gtk_widget_destroy ((GtkWidget *)dialog);
    if (palette_window)
        palette_window->about_dialog = NULL;
}

static void
palette_window_start_ime_about_dialog(GtkWidget   *menuitem,
				      palette_window_t *palette_window)
{
    GtkWidget *dialog;
    GtkWidget *hbox;
    GtkWidget *vbox;
    GtkWidget *stock;
    GtkWidget *label;
    GtkWidget *hbox1;
    GtkWidget *vbox_author;
    GtkWidget *vbox_copyright;
    char message[1024];
    char title[256];

#define ABOUT_IME_INDENT_SPACE   "    "

    if (palette_window->current_ime == NULL)
	return;

    DEBUG_printf ("about_dialog: %p\n", palette_window->about_dialog);
    if (palette_window->about_dialog != NULL)
	gtk_widget_destroy(palette_window->about_dialog);

    snprintf(title, 256, "%s%s%s", ABOUT_IME_TITLE, 
			     palette_window->current_ime->name,
			     ABOUT_IME_SUFFIX);

    dialog = gtk_dialog_new_with_buttons (title,
					  NULL,
					  GTK_DIALOG_DESTROY_WITH_PARENT,
					  GTK_STOCK_OK,
					  GTK_RESPONSE_NONE,
					  NULL);
    gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_CENTER);
    gtk_widget_show(dialog);

    hbox = gtk_hbox_new (FALSE, 8);
    gtk_widget_show(hbox);
    gtk_container_set_border_width (GTK_CONTAINER (hbox), 16);
    gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->vbox), hbox, FALSE, FALSE, 0);
  
    stock = gtk_image_new_from_stock (GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_DIALOG);
    gtk_widget_show(stock);
    gtk_box_pack_start (GTK_BOX (hbox), stock, FALSE, FALSE, 2);
  
    vbox = gtk_vbox_new (FALSE, 20);
    gtk_widget_show(vbox);
    gtk_box_pack_start (GTK_BOX (hbox), vbox, FALSE, FALSE, 0);

    snprintf(message, 1024, "%s%s    %s%d.%02d", 
		      palette_window->current_ime->name,
		      ABOUT_IME_SUFFIX,
		      ABOUT_IME_VERSION,
		      palette_window->current_ime->version/100,
		      palette_window->current_ime->version%100);

    label = gtk_label_new (message);
    gtk_widget_show(label);
    gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    vbox_author = gtk_vbox_new (FALSE, 3);
    gtk_widget_show(vbox_author);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_author, FALSE, FALSE, 0);

    label = gtk_label_new (ABOUT_IME_AUTHOR);
    gtk_widget_show(label);
    gtk_box_pack_start (GTK_BOX (vbox_author), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_author), hbox1, FALSE, FALSE, 0);

    label = gtk_label_new (ABOUT_IME_INDENT_SPACE);
    gtk_widget_show (label);
    gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = gtk_label_new (palette_window->current_ime->author);
    gtk_widget_show(label);
    gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    vbox_copyright = gtk_vbox_new (FALSE, 3);
    gtk_widget_show(vbox_copyright);
    gtk_box_pack_start (GTK_BOX (vbox), vbox_copyright, FALSE, FALSE, 0);

    label = gtk_label_new (ABOUT_IME_COPYRIGHT);
    gtk_widget_show(label);
    gtk_box_pack_start (GTK_BOX (vbox_copyright), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    hbox1 = gtk_hbox_new (FALSE, 0);
    gtk_widget_show (hbox1);
    gtk_box_pack_start (GTK_BOX (vbox_copyright), hbox1, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = gtk_label_new (ABOUT_IME_INDENT_SPACE);
    gtk_widget_show (label);
    gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    label = gtk_label_new (palette_window->current_ime->copyright);
    gtk_widget_show(label);
    gtk_box_pack_start (GTK_BOX (hbox1), label, FALSE, FALSE, 0);
    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);

    g_signal_connect(dialog,
		     "response",
		     G_CALLBACK(palette_window_destroy_ime_about_dialog),
		     palette_window);

    gtk_widget_show (dialog);

    palette_window->about_dialog = dialog;
}

GtkWidget *palette_window_create_utility_list_menu(palette_window_t *palette_window)
{
    GtkWidget *menu; 
    GtkWidget *menu_item;

    GtkWidget *icon_widget;
    GdkPixbuf *icon_pixbuf;

    char buf[128];

    gboolean tearoff = FALSE;

    menu = gtk_menu_new();

    if (tearoff) {
        menu_item = gtk_tearoff_menu_item_new ();
        gtk_menu_shell_append (GTK_MENU_SHELL (menu), menu_item);
        gtk_widget_show (menu_item);
    }

    menu_item = gtk_image_menu_item_new_with_mnemonic(MENU_ITEM_LABEL_VKB);
    icon_pixbuf = palette_window->pixbufs[PIXMAP_ID_VKB];
    icon_widget = gtk_image_new_from_pixbuf(icon_pixbuf);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  icon_widget);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    if (palette_window->vkb_list_menu == NULL)
        palette_window->vkb_list_menu = (GtkWidget *)palette_window_create_vkb_list_menu(palette_window);

    if (palette_window->vkb_list_menu != NULL) {
	gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_item), palette_window->vkb_list_menu);
    }

    menu_item = gtk_image_menu_item_new_with_mnemonic(MENU_ITEM_LABEL_CHARMAP);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  gtk_image_new_from_stock(GTK_STOCK_BOLD, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "activate",
		     G_CALLBACK(palette_window_start_uni_charmap_app),
		     (gpointer)palette_window);
    gtk_widget_show(menu_item);

    menu_item = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_check_menu_item_new_with_mnemonic(MENU_ITEM_LABEL_VERTICAL_STYLE);
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "toggled",
		     G_CALLBACK(palette_window_toggled_show_style_cb),
		     (gpointer)palette_window);
    if (palette_window->show_style == SHOW_STYLE_HORIZONTAL) {
        GTK_CHECK_MENU_ITEM(menu_item)->active = 0;
    } else {
        GTK_CHECK_MENU_ITEM(menu_item)->active = 1;
    }
    gtk_widget_show(menu_item);
    palette_window->utility_menuitem_show_vertical = menu_item;

    menu_item = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    menu_item = gtk_image_menu_item_new_with_mnemonic(MENU_ITEM_LABEL_TOOLBAR_PERFERENCES);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  gtk_image_new_from_stock(GTK_STOCK_PREFERENCES, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "activate",
		     G_CALLBACK(palette_window_start_ime_properties_app),
		     (gpointer)palette_window);
    gtk_widget_show(menu_item);

    menu_item = gtk_image_menu_item_new_with_mnemonic(MENU_ITEM_LABEL_HELP);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  gtk_image_new_from_stock(GTK_STOCK_HELP, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "activate",
		     G_CALLBACK(palette_window_start_ime_help_app),
		     (gpointer)palette_window);
    gtk_widget_show(menu_item);

    menu_item = gtk_separator_menu_item_new();
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    gtk_widget_show(menu_item);

    if (palette_window->current_ime == NULL)
        snprintf(buf, 127, "%s...", MENU_ITEM_LABEL_ABOUT);
    else
        snprintf(buf, 127, "%s%s...", MENU_ITEM_LABEL_ABOUT, palette_window->current_ime->name);
    menu_item = gtk_image_menu_item_new_with_mnemonic(buf);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "activate",
		     G_CALLBACK(palette_window_start_ime_about_dialog),
		     (gpointer)palette_window);
    gtk_widget_show(menu_item);

    gtk_widget_show(menu);

    g_signal_connect(G_OBJECT (menu),
                     "button_release_event",
                     G_CALLBACK (palette_window_menu_button_release_cb),
                     (gpointer)palette_window);

    g_object_set_data(G_OBJECT(menu),
		      DATA_PALETTE_AUX_WINDOW_INFO,
		      (gpointer)palette_window);

    return menu;
}

GtkWidget *palette_window_update_utility_list_menu(palette_window_t *palette_window)
{
    GtkWidget *menu; 
    GtkWidget *menu_item; 
    GList *list = NULL;

    char buf[128];

    menu = palette_window->utility_list_menu;
    if (menu == NULL)
	return NULL;

    if (palette_window->show_style == SHOW_STYLE_HORIZONTAL) {
        GTK_CHECK_MENU_ITEM(palette_window->utility_menuitem_show_vertical)->active = 0;
    } else {
        GTK_CHECK_MENU_ITEM(palette_window->utility_menuitem_show_vertical)->active = 1;
    }

    /* remove the last menu item "About IME..." */
    list = g_list_last(GTK_MENU_SHELL(menu)->children);
    GTK_MENU_SHELL(menu)->children = g_list_remove(GTK_MENU_SHELL(menu)->children,
						   list->data);

    /* add new menu item for the current IME */
    if (palette_window->current_ime == NULL)
        snprintf(buf, 127, "%s...", MENU_ITEM_LABEL_ABOUT);
    else
        snprintf(buf, 127, "%s%s...", MENU_ITEM_LABEL_ABOUT, palette_window->current_ime->name);

    menu_item = gtk_image_menu_item_new_with_mnemonic(buf);
    gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(menu_item),
				  gtk_image_new_from_stock(GTK_STOCK_DIALOG_INFO, GTK_ICON_SIZE_MENU));
    gtk_menu_shell_append(GTK_MENU_SHELL(menu), menu_item);
    g_signal_connect(G_OBJECT(menu_item), "activate",
		     G_CALLBACK(palette_window_start_ime_about_dialog),
		     (gpointer)palette_window);
    gtk_widget_show(menu_item);

    return menu;
}
