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

#include <gtk/gtk.h>
#include <X11/Xlib.h>
#include <gdk/gdkx.h>
#include <time.h>

#include "callbacks.h"
#include "interface.h"
#include "support.h"

char clientID[IDLENGTH];
GdkPixmap *pixmap_lock;
extern GtkWidget *dialog_IDinput;
extern GtkWidget *dialog_wait;
extern GtkWidget *dialog_recvAdv;
extern GtkWidget *recvAdv_label;
extern GtkWidget *dialog_inputmiss;
extern GtkWidget *lock_window;
GtkWidget *lock_screen;
extern GtkWidget *mini_window;
GtkWidget *mini_drawingarea;
GdkPixmap *mini_pixmap;
extern int auto_flag;
GtkWidget *dialog_exit;
extern PangoFontDescription *font_dsp;


/****************************************************************
 *サーバから送信された画像を表示するためのウィンドウで使用する
 *関数
 ****************************************************************/

gboolean
on_drawing_window_delete_event         (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  return TRUE;
}


gboolean
on_drawingarea_configure_event        (GtkWidget       *widget,
                                        GdkEventConfigure *event,
                                        gpointer         user_data)
{
  if (gdkpixmap[0][0])
    gdk_pixmap_unref(gdkpixmap[0][0]);

  gdkpixmap[0][0] = gdk_pixmap_new(widget->window,
				   widget->allocation.width,
				   widget->allocation.height, -1);

  gdk_draw_rectangle(gdkpixmap[0][0], widget->style->white_gc, TRUE,
		     0, 0, widget->allocation.width, widget->allocation.height);

  CreateImageInfoForClient();
  if (gdkimage[0] != NULL) {
    draw_image(gdkpixmap[0][0], gdkGC, gdkimage[0], 0, 0, 0, 0,
               gdkimage[0]->width, gdkimage[0]->height);
  }

  gdk_window_show(GDK_WINDOW(widget->window));
  return TRUE;
}


gboolean
on_drawingarea_expose_event           (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{
  gdk_draw_pixmap(widget->window,
		  widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
		  gdkpixmap[0][0],
		  event->area.x, event->area.y,
		  event->area.x, event->area.y,
		  event->area.width, event->area.height);

  return FALSE;
}


/****************************************************************
 *ID入力ダイアログで使用する関数
 ****************************************************************/
gboolean
on_dialog_IDinput_delete_event         (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  return TRUE;
}


void
on_dialog_IDinput_entry_editing_done   (GtkCellEditable *celleditable,
                                        gpointer         user_data)
{
  if (strlen((char *)gtk_entry_get_text(GTK_ENTRY(celleditable))) < 1) {
    return;
  }
  strcpy(clientID, (char *)gtk_entry_get_text(GTK_ENTRY(celleditable)));
  printf("clientID(edit done): %s\n", clientID);

}


void
on_dialog_IDinput_entry_changed       (GtkEditable     *editable,
                                        gpointer         user_data)
{
  strcpy(clientID, (char *)gtk_entry_get_text(GTK_ENTRY(editable)));
}


void
on_dialog_IDinput_buttonOK_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  if (strlen(clientID) < 1) {
    return;
  }
  memcpy((char *)client_CB.client_ID, clientID, IDLENGTH);
  printf("clientID(ok click): %s\n", client_CB.client_ID);

  gtk_grab_remove(dialog_IDinput);
  gtk_widget_destroy(dialog_IDinput);
  gtk_main_quit();
  if (client_CB.mltdsp != 0)
    client_CB.g_mltdsp = gdk_input_add (client_CB.mltdsp, GDK_INPUT_READ, \
					(GdkInputFunction)GetMultiVNCServerMsg, (gpointer)client_CB.mltdsp);
  dialog_wait = create_dialog_wait();
  gtk_widget_show(dialog_wait);
  gtk_grab_add(dialog_wait);
  draw_string_to_mini_window(_("Wait"));
}


void
on_dialog_IDinput_buttonCancel_clicked (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_main_quit();
  CloseVNCServer();

  exit(0);
}


/****************************************************************
 *「待機中」のメッセージを表示するためのダイアログで使用する関数
 ****************************************************************/
gboolean
on_dialog_wait_delete_event            (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  return TRUE;
}


void
on_dialog_wait_buttonStop_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
  gdk_input_remove(client_CB.g_mltdsp);
  gtk_grab_remove(dialog_wait);
  gtk_widget_destroy(dialog_wait);
  dialog_wait = NULL;

  dialog_IDinput = create_dialog_IDinput();
  gtk_widget_show(dialog_IDinput);
  gtk_grab_add(dialog_IDinput);
  draw_string_to_mini_window(_("Input ID"));
  gtk_main();
}


/****************************************************************
 *接続するサーバを確認するためのダイアログで使用する関数
 ****************************************************************/

void open_dialog_recvAdv(char *server_ID)
{
  char recvAdv_msg[256];

  dialog_recvAdv = create_dialog_recvAdv();
  GtkWidget *recvAdv_label = lookup_widget(GTK_WIDGET(dialog_recvAdv), "recvAdv_label");
  //sprintf(recvAdv_msg, "\343\202\265\343\203\274\343\203\220\345\220\215\357\274\232%s\n\n\343\201\223\343\201\256\343\202\265\343\203\274\343\203\220\343\201\253\346\216\245\347\266\232\343\201\227\343\201\276\343\201\231\343\201\213?", serveradv.server_ID);
  sprintf(recvAdv_msg, _("Server Name : %s\n\nDo you connect to this server?"), server_ID);
  gtk_label_set_text(GTK_LABEL(recvAdv_label), recvAdv_msg);
  gtk_widget_show(dialog_recvAdv);
  gtk_grab_add(dialog_recvAdv);
  gtk_main();
}


gboolean
on_dialog_recvAdv_delete_event         (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  dialog_exit = create_dialog_exit();
  gtk_widget_show(dialog_exit);
  gtk_grab_add(dialog_exit);
//  draw_string_to_mini_window(_("Quit"));

  return TRUE;
}


void
on_dialog_recvAdv_buttonOK_clicked     (GtkButton       *button,
                                        gpointer         user_data)
{
  answer = 'y';
  gtk_grab_remove(dialog_recvAdv);
  gtk_widget_destroy(dialog_recvAdv);
  gtk_main_quit();
  draw_string_to_mini_window(_("Connect"));
}


void
on_dialog_recvAdv_buttonCancel_clicked (GtkButton       *button,
                                        gpointer         user_data)
{
  answer = 'n';
  gtk_grab_remove(dialog_recvAdv);
  gtk_widget_destroy(dialog_recvAdv);
  gtk_main_quit();

  dialog_wait = create_dialog_wait();
  gtk_widget_show(dialog_wait);
  gtk_grab_add(dialog_wait);
  draw_string_to_mini_window(_("Wait"));
}


/****************************************************************
 *IDの再入力を促すメッセージを表示するためのダイアログで使用する
 *関数
 ****************************************************************/
gboolean
on_dialog_inputmiss_delete_event       (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  return TRUE;
}


void
on_dialog_inputmiss_buttonOK_clicked   (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_grab_remove(dialog_inputmiss);
  gtk_widget_destroy(dialog_inputmiss);
  gtk_main_quit();
}


/****************************************************************
 *クライアントロック機能で使用される関数
 ****************************************************************/

/*
  マウスポインタを閉じ込めるためのウィンドウの作成
 */
void
create_lock_window (void)
{
  SETLOCK_C(1);
  lock_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request (lock_window, 300, 200);
//  gtk_window_set_title (GTK_WINDOW (lock_window), _("MultiVNC \346\223\215\344\275\234\343\203\255\343\203\203\343\202\257\347\224\250\343\202\246\343\202\243\343\203\263\343\203\211\343\202\246"));
  gtk_window_set_title (GTK_WINDOW (lock_window), _("MultiVNC Lock"));

  lock_screen = gtk_drawing_area_new ();
  gtk_widget_show (lock_screen);
  gtk_container_add (GTK_CONTAINER (lock_window), lock_screen);

  g_signal_connect ((gpointer) lock_screen, "configure_event",
                    G_CALLBACK (on_lock_screen_configure_event),
                    NULL);
  g_signal_connect ((gpointer) lock_screen, "expose_event",
                    G_CALLBACK (on_lock_screen_expose_event),
                    NULL);

  draw_string_to_mini_window(_("Lock"));
  gtk_widget_show(lock_window);
  gtk_grab_add(lock_window);
}


gboolean
on_lock_screen_configure_event    (GtkWidget       *widget,
                                        GdkEventConfigure *event,
                                        gpointer         user_data)
{
  GdkGC *gc;
  GdkColor color;
  const char* fontsname = "Bitstream Vesa Sans 18";
  font_dsp = pango_font_description_from_string(fontsname);
  gtk_widget_modify_font (lock_window, font_dsp);

  PangoLayout *layout = gtk_widget_create_pango_layout(lock_window, _("Now Locking ..."));
  pango_layout_set_justify(layout, TRUE);

  if (pixmap_lock)
    gdk_pixmap_unref(pixmap_lock);

  pixmap_lock = gdk_pixmap_new(widget->window,
			       widget->allocation.width,
			       widget->allocation.height, -1);

  gc = gdk_gc_new(widget->window);
  color.red = 0xffff;
  color.green = 0x0000;
  color.blue = 0x0000;
  gdk_color_alloc(gdk_colormap_get_system(), &color);
  gdk_gc_set_foreground(gc, &color);
  gdk_draw_rectangle(pixmap_lock, gc, TRUE,
		     0, 0, widget->allocation.width, widget->allocation.height);

  gdk_draw_layout(pixmap_lock, widget->style->black_gc, 50, 100, layout);

  return TRUE;
}


gboolean
on_lock_screen_expose_event       (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{
  gdk_draw_pixmap(widget->window,
		  widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
		  pixmap_lock,
		  event->area.x, event->area.y,
		  event->area.x, event->area.y,
		  event->area.width, event->area.height);

  /* マウスポインタの捕獲 */
  gdk_keyboard_grab(widget->window, FALSE, GDK_CURRENT_TIME);
  gdk_pointer_grab(widget->window, FALSE, 0, gtk_widget_get_parent_window(widget), NULL, GDK_CURRENT_TIME);

  return FALSE;
}


/*
  マウスポインタをロック用windowに閉じ込める関数
 */
void
start_lock(void)
{
  /* マウスポインタを以前のロックから解放 */
  gdk_keyboard_ungrab(GDK_CURRENT_TIME);
  gdk_pointer_ungrab(GDK_CURRENT_TIME);

  /* マウスポインタの捕獲 */
  gdk_keyboard_grab(lock_screen->window, FALSE, GDK_CURRENT_TIME);
  gdk_pointer_grab(lock_screen->window, FALSE, 0, gtk_widget_get_parent_window(lock_screen), NULL, GDK_CURRENT_TIME);
}


/*
  ロックを解除する関数
 */
void
stop_lock(void)
{
  if (GETLOCK_C) {
    SETLOCK_C(0);
    draw_string_to_mini_window(_("Connect"));
    //XUngrabKeyboard(dpy, CurrentTime);
    //XUngrabPointer(dpy, CurrentTime);
    gdk_keyboard_ungrab(GDK_CURRENT_TIME);
    gdk_pointer_ungrab(GDK_CURRENT_TIME);
    gtk_grab_remove(lock_window);
    gtk_widget_destroy(lock_window);
    lock_window = NULL;
  }
}


/****************************************************************
 *現在の状態を表示するウィンドウ(mini_window)で使用する関数
 ****************************************************************/

/*
  mini_windowの作成
 */
GtkWidget*
create_mini_window (void)
{
  GtkWidget *mini_window;

  mini_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
  gtk_widget_set_size_request (mini_window, MINI_WIND_WIDTH, MINI_WIND_HEIGHT);
  gtk_window_set_title (GTK_WINDOW (mini_window), _("MultiVNC"));
  gtk_window_set_resizable (GTK_WINDOW (mini_window), FALSE);

  mini_drawingarea = gtk_drawing_area_new ();
  gtk_widget_show (mini_drawingarea);
  gtk_container_add (GTK_CONTAINER (mini_window), mini_drawingarea);

  g_signal_connect ((gpointer) mini_window, "delete_event",
                    G_CALLBACK (on_mini_window_delete_event),
                    NULL);
  g_signal_connect ((gpointer) mini_drawingarea, "configure_event",
                    G_CALLBACK (on_mini_drawingarea_configure_event),
                    NULL);
  g_signal_connect ((gpointer) mini_drawingarea, "expose_event",
                    G_CALLBACK (on_mini_drawingarea_expose_event),
                    NULL);

  return mini_window;
}


gboolean
on_mini_window_delete_event            (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  dialog_exit = create_dialog_exit();
  gtk_widget_show(dialog_exit);
  gtk_grab_add(dialog_exit);

  return TRUE;
}



gboolean
on_mini_drawingarea_configure_event    (GtkWidget       *widget,
                                        GdkEventConfigure *event,
                                        gpointer         user_data)
{
  if (mini_pixmap)
    gdk_pixmap_unref(mini_pixmap);

  mini_pixmap = gdk_pixmap_new(widget->window,
			       widget->allocation.width,
			       widget->allocation.height, -1);

//  if (auto_flag != 0) {
    draw_string_to_mini_window(_("Input ID"));
//  } else {
//    draw_string_to_mini_window(_("Connect"));
//  }

  return TRUE;
}


gboolean
on_mini_drawingarea_expose_event       (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{
  gdk_draw_pixmap(widget->window,
		  widget->style->fg_gc[GTK_WIDGET_STATE(widget)],
		  mini_pixmap,
		  event->area.x, event->area.y,
		  event->area.x, event->area.y,
		  event->area.width, event->area.height);

  return FALSE;
}


/*
  mini_windowにメッセージを表示する関数
 */
void
draw_string_to_mini_window(char *string)
{
  GdkRectangle gdkrect;
  GdkGC *gc;
  GdkColor color;
  const char* fontsname = "Bitstream Vesa Sans 24";
//  const char* fontsname = "IPAUIGothic 24";
  font_dsp = pango_font_description_from_string(fontsname);
  gtk_widget_modify_font (mini_window, font_dsp);

  PangoLayout *layout = gtk_widget_create_pango_layout(mini_window, _(string));
  pango_layout_set_justify(layout, TRUE);

  if (notice_flag == 1) {
    gc = mini_drawingarea->style->white_gc;
    gdk_draw_rectangle(mini_pixmap, gc, TRUE,
		       0, 0, mini_drawingarea->allocation.width, mini_drawingarea->allocation.height);
    gdk_draw_layout(mini_pixmap, mini_drawingarea->style->black_gc, 0, 0, layout);

    gdkrect.x = 0;
    gdkrect.y = 0;
    gdkrect.width = mini_drawingarea->allocation.width;
    gdkrect.height = mini_drawingarea->allocation.height;
    gtk_widget_draw(mini_drawingarea, &gdkrect);
  }
}

// 1.4.2 non implementation
void change_status_mini_window() {
    char status[STRLENGTH];
    switch (client_CB.state) {
        case 0:
            strcpy(status, _("Wait"));
            break;
//        default:
    }
    draw_string_to_mini_window(status);
}

gboolean
on_dialog_exit_delete_event            (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_exit);
  gtk_grab_remove(dialog_exit);

  return TRUE;
}


void
on_dialog_exit_buttonOK_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_exit);
  gtk_grab_remove(dialog_exit);
  gtk_widget_destroy(mini_window);
  CloseVNCServer();
  exit(0);
}


void
on_dialog_exit_buttonCancel_clicked    (GtkButton       *button,
                                        gpointer         user_data)
{
  gtk_widget_destroy(dialog_exit);
  gtk_grab_remove(dialog_exit);
}

