/*
 * gui_callbacks.c
 * 
 * Copyright (C) 2005-2007  Josef Kufner <jk@myserver.cz>
 * 
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 * vim:encoding=utf8:
 */
#ifdef HAVE_CONFIG_H
#  include <config.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <errno.h>
#include <time.h>
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

#define DEBUG 		3
#include "debug.h"

#include "gui_callbacks.h"
#include "gui.h"
#include "options.h"
#include "connection.h"
#include "session.h"
#include "backend.h"
#include "draw.h"
#include "message.h"
#include "roles.h"

/* from draw.c  --  because window redrawing */
extern GdkPixbuf *draw_board;


/*****************************************************************************
 * 	GUI Callbacks
 ****************************************************************************/

gboolean
on_main_window_destroy                 (GtkWidget       *widget,
                                        GdkEvent        *event,
                                        gpointer         user_data)
{
	
	if (gui_exit_question())
		status_switch(connection_status, S_C_EXITING, NULL);

	return TRUE;
}


void
on_chat_entry_activate                 (GtkEntry        *entry,
                                        gpointer         user_data)
{
	char *msg = (char*)gtk_entry_get_text(entry);
	MESSAGE *m;
	
	if (msg[0] == '/' && msg[1] != '/') {
		/* game backend */
		m = message_create('C', 'G');
		message_append(m, MESSAGE_PART_DATA, MESSAGE_STRING, "G/", MESSAGE_STRING, msg + 1, MESSAGE_END);
	} else {
		/* klasicky chat */
		m = message_create('C', 'N');
		message_append(m, MESSAGE_PART_DATA, MESSAGE_STRING, "C", MESSAGE_STRING, msg, MESSAGE_END);
	}
	message_send(m);
	message_destroy(m);

	/* vymazat text z chat_entry */
	gtk_entry_set_text(GTK_ENTRY(lookup_widget(main_window, "chat_entry")), "");
}

/****************************************************************************/

void
on_connect_btn_cancel_clicked          (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_destroy(dialog_connect);
}


void
on_connect_btn_ok_clicked              (GtkButton       *button,
                                        gpointer         user_data)
{
	const char *mod, *backend;
	GtkComboBox *combobox;
	GtkTreeIter backend_iter;

	gtk_widget_hide(dialog_connect);
	combobox = GTK_COMBO_BOX(lookup_widget(dialog_connect, "profile_combobox"));

	option_set_string("main", "net", "address", gtk_entry_get_text(GTK_ENTRY(lookup_widget(dialog_connect, "address_entry"))));

	if (gtk_combo_box_get_active_iter(combobox, &backend_iter)) {
		gtk_tree_model_get(gtk_combo_box_get_model(combobox), &backend_iter, 1, &mod, -1);
		backend = option_get_string("network", mod, "backend");
		
		option_set_string("main", "net", "profile", mod ? mod : "");
		option_set_string("main", "net", "backend", backend ? backend : "");

		status_switch(connection_status, S_C_CONNECTING, NULL);
	} else {
		option_set_string("main", "net", "profile", "");
	}


	gtk_widget_destroy(dialog_connect);
}


void
on_connect_profile_combobox_changed    (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	GtkTreeIter iter;
	char *addr = NULL;
	
	if (gtk_combo_box_get_active_iter(combobox, &iter)) {
		gtk_tree_model_get(gtk_combo_box_get_model(combobox), &iter, 2, &addr, -1);
		if (addr && addr[0])
			gtk_entry_set_text(GTK_ENTRY(lookup_widget(dialog_connect, "address_entry")), addr);
	}
}


void
on_profile_config_button_clicked       (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkComboBox *combobox;
	GtkTreeIter iter;
	char *mod = NULL;
	
	combobox = GTK_COMBO_BOX(lookup_widget(dialog_connect, "profile_combobox"));
	
	if (combobox && gtk_combo_box_get_active_iter(combobox, &iter)) {
		gtk_tree_model_get(gtk_combo_box_get_model(combobox), &iter, 1, &mod, -1);
		gtk_widget_destroy(dialog_connect);
		gui_show_network_backend_config(mod);
	}
}


/****************************************************************************/

void
on_dialog_connect_destroy              (GtkObject       *object,
                                        gpointer         user_data)
{

}

/****************************************************************************/

void
on_btn_about_close_clicked             (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_destroy(dialog_about);
}

void
on_dialog_about_destroy                (GtkObject       *object,
                                        gpointer         user_data)
{
	gtk_widget_destroy(dialog_about);
}



void
on_btn_restart_clicked                 (GtkToolButton   *toolbutton,
                                        gpointer         user_data)
{
}


void
on_main_notebook_switch_page           (GtkNotebook     *notebook,
                                        GtkNotebookPage *page,
                                        guint            page_num,
                                        gpointer         user_data)
{
	switch (page_num) {
		case GUI_PAGE_BOARD:
			gtk_widget_hide(lookup_widget(main_window, "board_label_image"));
			gtk_widget_grab_focus(lookup_widget(main_window, "board_drawingarea"));
			break;
		case GUI_PAGE_CHAT:
			gtk_widget_hide(lookup_widget(main_window, "chat_label_image"));
			gtk_widget_grab_focus(lookup_widget(main_window, "chat_entry"));
			break;
	}

}


gboolean
on_board_drawingarea_expose             (GtkWidget       *widget,
                                        GdkEventExpose  *event,
                                        gpointer         user_data)
{
/*	if (draw_board) {
		gdk_draw_pixbuf(widget->window, NULL, draw_board,
				event->area.x, event->area.y,
				event->area.x, event->area.y,
				event->area.width, event->area.height,
				GDK_RGB_DITHER_NORMAL, 0, 0);
	}
*/
	//draw_refresh( event->area.x, event->area.y, event->area.width, event->area.height,);
	draw_all_real();
	return TRUE;
}


gboolean
on_board_drawingarea_button_press_event (GtkWidget       *widget,
                                        GdkEventButton  *event,
                                        gpointer         user_data)
{
	MESSAGE *m;
	long object;

	/*MSG* Bbp button obj_id x y
	 *
	 * Board Button Press
	 *
	 * Event notification: Mouse button 'button' was pressed at [x,y] where object 'obj_id' is.
	 */

	object = draw_get_object_by_xy(event->x, event->y);
	m = message_create('B', 'G');
	message_append(m, MESSAGE_PART_DATA, MESSAGE_STRING, "Bbp",
			MESSAGE_INTEGER, (long) event->button,
			MESSAGE_INTEGER, (long) object,
			MESSAGE_INTEGER, (long) event->x,
			MESSAGE_INTEGER, (long) event->y,
			MESSAGE_END);
	message_send(m);
	message_destroy(m);
	DBG_MSG(3, "Button press event: button %d at [ %0.0lf, %0.0lf ]", event->button, event->x, event->y);
	return FALSE;
}


gboolean
on_board_drawingarea_button_release_event
                                        (GtkWidget      *widget,
                                        GdkEventButton  *event,
                                        gpointer         user_data)
{
	MESSAGE *m;
	long object;

	/*MSG* Bbp button obj_id x y
	 *
	 * Board Button Release
	 *
	 * Event notification: Mouse button 'button' was released at [x,y] where object 'obj_id' is.
	 */
	
	object = draw_get_object_by_xy(event->x, event->y);
	m = message_create('B', 'G');
	message_append(m, MESSAGE_PART_DATA, MESSAGE_STRING, "Bbr",
			MESSAGE_INTEGER, (long)event->button,
			MESSAGE_INTEGER, (long)object,
			MESSAGE_INTEGER, (long)event->x,
			MESSAGE_INTEGER, (long)event->y,
			MESSAGE_END);
	message_send(m);
	message_destroy(m);
	DBG_MSG(3, "Button release event: button %d at [ %0.0lf, %0.0lf ]", event->button, event->x, event->y);
	return FALSE;
}


gboolean
on_board_drawingarea_key_event          (GtkWidget       *widget,
                                        GdkEventKey     *event,
                                        gpointer         user_data)
{
	/*MSG* Bbp state keyval string
	 *
	 * Board Key Press
	 *
	 * Event notification: Key was pressed. See GdkEventKey in GDK documentation for details.
	 */
	
	/*MSG* Bbp state keyval string
	 *
	 * Board Key Release
	 *
	 * Event notification: Key was released. See GdkEventKey in GDK documentation for details.
	 */
	
	DBG_MSG(3, "Key %s event: keyval %d, string \"%s\", mods 0x%04x",
			event->type == GDK_KEY_PRESS ? "press" : "release",
			event->keyval, event->string, event->state);

	/* Ignore events with alt and/or ctrl */
	if ((event->state & (GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0) {
		MESSAGE *m;
		m = message_create('B', 'G');
		message_append(m, MESSAGE_PART_DATA, MESSAGE_STRING, event->type == GDK_KEY_PRESS ? "Bkp" : "Bkr",
				MESSAGE_INTEGER, event->state,
				MESSAGE_INTEGER, event->keyval,
				MESSAGE_STRING, event->string,
				MESSAGE_END);
		message_send(m);
		message_destroy(m);
		return TRUE;
	} else {
		return FALSE;
	}
}


/*****************************************************************************
 *	Menu
 ****************************************************************************/

/***** Connect *****/

void
on_network_connect_activate            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_show_dialog_connect();
}


void
on_network_disconnect_activate         (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	status_switch(connection_status, S_C_DISCONNECTING, NULL);
}


void
on_network_reconnect_activate          (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	status_switch(connection_status, S_C_RECONNECT, NULL);
}


void
on_mnu_exit_activate                   (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	if (gui_exit_question())
		status_switch(connection_status, S_C_EXITING, NULL);
}

/***** Game *****/

void
on_game_select_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_show_dialog_game_select();
}


void
on_game_start_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	status_switch(session_status, S_S_READY, NULL);
}


void
on_game_load_abort_activate            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	status_switch(session_status, S_S_LOAD_ABORT, NULL);
}


void
on_game_surrender_activate             (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gint response;
	GtkWidget *d;
	
	d = gtk_message_dialog_new(GTK_WINDOW(main_window), GTK_DIALOG_MODAL, GTK_MESSAGE_QUESTION,
			GTK_BUTTONS_NONE, _("Opravdu chcete ukončit hru ?"));
	gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(d),
			_("Hmm..."));
	gtk_dialog_add_buttons(GTK_DIALOG(d),
			GTK_STOCK_QUIT, GTK_RESPONSE_ACCEPT,
			GTK_STOCK_GO_BACK, GTK_RESPONSE_REJECT,
			NULL);
	gtk_dialog_set_default_response(GTK_DIALOG(d), GTK_RESPONSE_REJECT);
	response = gtk_dialog_run(GTK_DIALOG(d));
	gtk_widget_destroy(d);
	
	if (response == GTK_RESPONSE_ACCEPT) {
		session_surrender();
	}
}


void
on_game_terminate_activate             (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	status_switch(session_status, S_S_KILL, NULL);
}


void
on_game_synchronize_activate           (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	session_send_sync_rq();
}


void
on_game_pause_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_game_load_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_game_save_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_game_lock_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_game_screenshot_activate            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	time_t t;
	struct tm *tmp;
	char *filename, date[16] = "today";
	
	DBG_MSG(1, "");
	
	t = time(NULL);
	tmp = localtime(&t);
	if (tmp == NULL) {
		perror("localtime");
	}
	if (strftime(date, sizeof(date), "%Y%m%d-%H%M%S", tmp) == 0) {
		perror("strftime");
	}
	filename = g_strdup_printf("%s-%s-%ld.png",
			date, option_get_string("main", "game", "backend"),
			status_get_time(session_status));
	
	gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Ukládám \"%s\" ..."), filename);

	switch (draw_save_screenshot_png(option_get_string("main", "dir", "screenshot") ? : getenv("HOME"), filename)) {
		case -1:
			gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Herní deska je prázdná."));
			break;
		case 1:
			gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Obrázek uložen do \"%s\"."), filename);
			break;
	}


	g_free(filename);
}


/***** Preferences *****/

void
on_players_columns_activate            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	char *opt = (char *) user_data;
	option_set_integer("main", "ui", opt, gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)));
}


void
on_pref_behavior_activate              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	MESSAGE *msg;

	msg = message_create('O', 'O');
	message_append(msg, MESSAGE_PART_DATA, MESSAGE_STRING, "Odo",
			MESSAGE_STRING, "main",
			MESSAGE_STRING, "ui",
			MESSAGE_STRING, _("Chování"),
			MESSAGE_STRING, _("[Automaticky"),
			MESSAGE_STRING, _("?Přepínat taby"), MESSAGE_STRING, "autoswitch",
			MESSAGE_STRING, _("?Rozbalovat/sbalovat ovládací prvky"), MESSAGE_STRING, "autoexpand",
			MESSAGE_STRING, _("[Po spuštění"),
			MESSAGE_STRING, _("?Zobrazit okno \"Navázání spojení\""), MESSAGE_STRING, "show_connect_on_startup", 
			MESSAGE_STRING, _("[Zobrazovat"),
			MESSAGE_STRING, _("?Odpojené účastníky hry"), MESSAGE_STRING, "show_disconnected", 
			MESSAGE_STRING, _("?Menu \"Debug\""), MESSAGE_STRING, "show_debug_menu", 
			MESSAGE_END);
	message_send(msg);
	message_destroy(msg);
}



void
on_pref_detach_page_activate           (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

	DBG_MSG(3, "");

	if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(menuitem)))
		gui_detach_page((int)user_data);
	else
		gui_atach_page((int)user_data);
}


void
on_detached_widget_destroy             (GtkWidget	*widget,
                                        gpointer	 user_data)
{

	DBG_MSG(3, "");
	gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(user_data), FALSE);
}


void
on_pref_paths_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	MESSAGE *msg;

	msg = message_create('O', 'O');
	message_append(msg, MESSAGE_PART_DATA, MESSAGE_STRING, "Odo",
			MESSAGE_STRING, "main", MESSAGE_STRING, "dir",
			MESSAGE_STRING, _("Nastavení cest"),
			MESSAGE_STRING, _("[Adresáře"),
			MESSAGE_STRING, _("$_Základní"), MESSAGE_STRING, "base",
			MESSAGE_STRING, _("$_Data her"), MESSAGE_STRING, "data",
			MESSAGE_STRING, _("$_Herní moduly"), MESSAGE_STRING, "game",
			MESSAGE_STRING, _("$_Síťové moduly"), MESSAGE_STRING, "network",
			MESSAGE_STRING, _("$_Screenshoty"), MESSAGE_STRING, "screenshot",
			MESSAGE_STRING, _("[Soubory"),
			MESSAGE_STRING, _("$Hlavní _konfigurace"), MESSAGE_STRING, "config_file",
			MESSAGE_STRING, _("$Načíst _po startu"), MESSAGE_STRING, "startup_file",
			MESSAGE_STRING, _("[Informace"),
			MESSAGE_STRING, _("=Po spuštění a načtení hlavního konfiguračního "
				"souboru je změněn pracovní adresář na Základní (chdir). "
				"Ostatní adresáře jsou tedy vztaženy k tomuto."),
			MESSAGE_STRING, _("=Screenshoty jsou ukládány do souborů pojmenovaných ve tvaru "
				"<tt>YYYYMMDD-HHMMSS-<i>jménohry</i>-<i>čashry</i>.png</tt>."),
			MESSAGE_END);
	message_send(msg);
	message_destroy(msg);
}


void
on_pref_net_profiles_activate          (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	if (!dialog_network_profiles)
		gui_show_network_profiles();
}


void
on_pref_browser_activate               (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	if (dialog_option_browser)
		gtk_widget_grab_focus(dialog_option_browser);
	else
		gui_show_option_browser();
}


void
on_pref_save_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_store_options_with_info();
}

/***** Debug *****/

void
on_debug_options_activate              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	MESSAGE *msg;

	msg = message_create('O', 'O');
	message_append(msg, MESSAGE_PART_DATA, MESSAGE_STRING, "Odo",
			MESSAGE_STRING, "main",
			MESSAGE_STRING, "debug",
			MESSAGE_STRING, _("Nastavení ladicích funkcí"),
			MESSAGE_STRING, _("[Logy"),
			MESSAGE_STRING, _("?Zobrazovat taby"), MESSAGE_STRING, "show_logs",
			MESSAGE_STRING, _("?Zaznamenávat komunikaci (+20 % zátěž)"), MESSAGE_STRING, "enable_comm_log",
			MESSAGE_STRING, _("[Stav"),
			MESSAGE_STRING, _("?Zobrazovat tab"), MESSAGE_STRING, "show_status_tab", 
			MESSAGE_STRING, _("[Záznam"),
			MESSAGE_STRING, _("?Zapnuto"), MESSAGE_STRING, "record_enabled", 
			MESSAGE_STRING, _("?Zobrazovat tab"), MESSAGE_STRING, "show_record_tab", 
			MESSAGE_STRING, _("[Ping test"),
			MESSAGE_STRING, _("#Počet opakování"), MESSAGE_STRING, "ping_loops", MESSAGE_INTEGER, 0, MESSAGE_INTEGER, 1000,
			MESSAGE_STRING, _("?Před pingáním prověřit časomíru"), MESSAGE_STRING, "do_timer_test", 
			MESSAGE_END);
	message_send(msg);
	message_destroy(msg);
}


void
on_debug_draw_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	const char *dir_test = option_get_string("main", "dir", "data");
	gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Test: Vykreslovací test"));
	draw_remove_all();
	draw_image_load(dir_test, "boards/chess-wsb.png", 0);
	draw_object_add(0, 0, 0, 0, -1, -1);
	draw_image_load(dir_test, "cursors/chess-selected.png", 1);
	draw_object_add(1, 1, 128, 128, -1, -1);
	draw_object_add(2, 1, 64, 384, -1, -1);
	draw_image_load(dir_test, "cursors/chess-focus.png", 2);
	draw_object_add(3, 2, 320, 256, -1, -1);
	draw_object_add(4, 2, 384, 384, -1, -1);
	draw_image_load(dir_test, "pieces/chess-pawn-white.png", 10);
	draw_object_add(10, 10, 128, 128, -1, -1);
	draw_object_add(11, 10, 128, 256, -1, -1);
	draw_object_add(12, 10, 320, 128, -1, -1);
	draw_object_add(13, 10, 320, 256, -1, -1);
	gui_switch_main_page(GUI_PAGE_BOARD);
	draw_all();
}


void
on_debug_clean_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Test: Vymazání hrací desky"));
	draw_remove_all();
	gui_switch_main_page(GUI_PAGE_BOARD);
	draw_all();
}


void
on_debug_dialog_activate               (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	char *p = NULL;
	MESSAGE *msg;

	msg = message_from_string(0, 'O',
		"( \"Odo\" \"network\" \"test-dialog\" \"Testovací dialog\" "
			"\"[Command line\" "
				"\"=command arg1 arg2 ...\" "
			"\"[Frame 1\" "
				"\"\\$_Text entry 1\"	\"textentry\" "
				"\"\\$_Text entry 2\"	\"textentry2\" "
				"\"*_Password entry\"	\"passwordentry\" "
				"\"?_Check button\"	\"checkbutton\" "
			"\"[Frame 2\" "
				"\"%Combo _Box\"	\"combobox\" "
							"\"jedna\" \"dva\" \"tři\" \"čtyři\" \"\" "
				"\"#_Spin button\"		\"spinbutton\" -1000 1000 "
			"\"[Text Frame\" "
				"\"=Lorem ipsum dolor sit amet, consectetuer adipiscing elit, sed "
				  "diam nonummy nibh euismod <b>tincidunt</b> ut laoreet "
				  "dolore magna aliquam erat volutpat. Ut <i>wisi enim</i> "
				  "ad minim veniam, <u>quis nostrud</u> exerci tation "
				  "ullamcorper suscipit lobortis nisl ut aliquip ex ea commodo consequat.\" "
				"\"=<span foreground='blue' weight='bold' size='x-large'>Blue text "
				  "is <i>cool !</i></span>\" "
		")", &p);
	message_send(msg);
	message_destroy(msg);
}


void
on_debug_update_state_tab_activate     (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_update_status_tab();
}


void
on_debug_send_message_activate         (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_show_dialog_send_message();
}


void
on_debug_cleanlogs_activate             (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	gui_erase_logs();
}


void
on_debug_memusage_activate             (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	long mem_size, mem_resident, mem_shared;
	const char *filename = "/proc/self/statm";
	FILE *f;
	
	DBG_MSG(1, "");
	f = fopen(filename, "rt");
	if (f) {
		fscanf(f, " %ld %ld %ld", &mem_size, &mem_resident, &mem_shared);
		gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Memory usage: %ld B total, %ld B resident, %ld B shared"), mem_size, mem_resident, mem_shared);
		fclose(f);
	} else {
		gui_append_to_chat(NULL, GUI_CHAT_SYS, "%s: %s", filename, g_strerror(errno));
	}
}

/***** Help *****/

void
on_help_about_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
#include "licence.h"

	gtk_show_about_dialog(GTK_WINDOW(main_window),
			"name", "Net Board",
			"version", "2",
			"copyright", "Josef Kufner <jk@myserver.cz>",
			"website", "http://jk.myserver.cz/programy/netboard/",
			"comments",
				_("Univerzální dvourozměrná hrací deska.\n"
				"Vytvořeno jako semestrální práce\n"
				"na ČVUT - FEL v roce 2005\n"
				"a překopáno jako semestrální\n"
				"projekt v roce 2007.\n"),
			"license", the_licence,
			NULL);
}


void
on_hlp_rules_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}

/*****************************************************************************/

void
on_game_role_combobox_changed          (GtkComboBox     *combobox,
                                        gpointer         user_data)
{
	GtkTreeIter iter;
	char *role;
	gint role_id;
	int st = status_get(session_status);
	
	if (st == S_S_LOADED || st == S_S_READY) {
		DBG_MSG(1, "");
		gtk_combo_box_get_active_iter(combobox, &iter);
		roles_get_by_iter(&iter, &role, &role_id);
		
		if (role) {
			status_switch(session_status, S_S_ROLE_SELECT, role_id > 0 ? role : NULL);
		}
		if (role)
			g_free(role);
	}
}


void
on_game_name_button_clicked            (GtkButton       *button,
                                        gpointer         user_data)
{
	gui_show_dialog_game_select();
}


void
on_game_start_button_clicked           (GtkButton       *button,
                                        gpointer         user_data)
{
	on_game_start_activate(NULL, user_data);
}


void
on_dialog_game_select_destroy          (GtkObject       *object,
                                        gpointer         user_data)
{

}


void
on_game_select_cancelbutton_clicked    (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_widget_destroy(dialog_game_select);
}


void
on_game_select_okbutton_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkTreeView *treeview = GTK_TREE_VIEW(lookup_widget(dialog_game_select, "game_select_treeview"));
	GtkTreeIter iter;
	GtkTreeModel *model;
	GtkTreeSelection *selection = gtk_tree_view_get_selection(treeview);
	gchar *str = NULL;
	int st = status_get(session_status);
	
	if (st == S_S_IDLE || st == S_S_LOAD_ERROR) {
		/* nacist vybranou hry a nastavit ji do labelu */
		if (gtk_tree_selection_get_selected (selection, &model, &iter)) {
			gtk_tree_model_get(model, &iter, 0, &str, -1);
		}

		DBG_MSG(2, "game backend = \"%s\"", str);

		if (str) {
			status_switch(session_status, S_S_LOADING, str);
		}
	}
	gtk_widget_destroy(dialog_game_select);
}


void
on_dialog_option_browser_destroy       (GtkObject       *object,
                                        gpointer         user_data)
{
	option_set_update_callback(NULL);
	dialog_option_browser = NULL;
}



void
on_connection_connect_button_activate  (GtkButton       *button,
                                        gpointer         user_data)
{
	gui_show_dialog_connect();
}


void
on_gui_option_ok_button_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
	GUI_ODW_LIST *odw = (GUI_ODW_LIST *) user_data;
	GUI_ODW *odw_item;
	GSList *item;

	DBG_MSG(3, "");
	assert(odw != NULL);
	assert(odw->cat != NULL);
	assert(odw->mod != NULL);

	odw->ok_clicked = 1;
	
	for (item = odw->list; item; item = g_slist_next(item)) {
		odw_item = (GUI_ODW *) item->data; 
		DBG_MSG(7, "updating [ %s :: %s :: %s ] ...", odw->cat, odw->mod, odw_item->opt);
		switch (odw_item->type) {
			case GUI_ODW_T_NONE:
				break;
				
			case GUI_ODW_T_ENTRY:
				option_set_string(odw->cat, odw->mod, odw_item->opt, gtk_entry_get_text(GTK_ENTRY(odw_item->widget)));
				break;
				
			case GUI_ODW_T_CHECKBOX:
				option_set_integer(odw->cat, odw->mod, odw_item->opt, gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(odw_item->widget)));
				break;
				
			case GUI_ODW_T_NUMBER:
				option_set_integer(odw->cat, odw->mod, odw_item->opt, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(odw_item->widget)));
				break;
				
			case GUI_ODW_T_COMBO:
				option_set_string(odw->cat, odw->mod, odw_item->opt, gtk_combo_box_get_active_text(GTK_COMBO_BOX(odw_item->widget)));
				break;
		}
	}

	DBG_MSG(7, "destroying dialog");
	gtk_widget_destroy(gtk_widget_get_toplevel(GTK_WIDGET(button)));
	DBG_MSG(3, "done");
}


void
on_gui_option_destroy                  (GtkObject       *object,
                                        gpointer         user_data)
{
	GUI_ODW_LIST *odw = (GUI_ODW_LIST *) user_data;
	MESSAGE *msg;

	if (odw) {
		if (odw->notify_target) {
			msg = message_create('O', odw->notify_target);
			message_append(msg, MESSAGE_PART_DATA, MESSAGE_STRING, "Odc", MESSAGE_INTEGER, odw->ok_clicked, MESSAGE_END);
			message_send(msg);
			message_destroy(msg);
		}

		g_slist_free(odw->list);
		g_mem_chunk_destroy(odw->mem_chunk);
		g_free(odw);
	}
}


void
on_dialog_network_profiles_destroy     (GtkObject       *object,
                                        gpointer         user_data)
{
	dialog_network_profiles = NULL;
}


void
on_network_profile_edit_clicked        (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkTreeSelection *sel;
	GtkTreeModel *model;
	GtkTreeIter iter;
	char *id;
	
	if (user_data) {
		sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(dialog_network_profiles, "treeview")));
		
		if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
			gtk_tree_model_get(model, &iter, 0, &id, -1);
			gui_show_network_profile_editor(id, dialog_network_profiles);
		}
	}
}


void
on_network_profiles_treeview_row_activated
                                        (GtkTreeView     *treeview,
                                        GtkTreePath     *path,
                                        GtkTreeViewColumn *column,
                                        gpointer         user_data)
{
	gtk_widget_activate(lookup_widget(dialog_network_profiles, "network_profile_edit"));
}


void
on_network_profile_add_clicked         (GtkButton       *button,
                                        gpointer         user_data)
{
	char *id = NULL;
	int n = 0;
	char outstr[200];
	time_t t;
	struct tm *tmp;

	do {
		if (id)
			g_free(id);
		
		t = time(NULL);
		tmp = localtime(&t);
		if (tmp == NULL) {
			perror("localtime");
			exit(EXIT_FAILURE);
		}

		if (strftime(outstr, sizeof(outstr), "%Y%m%d.%H%M%S", tmp) == 0) {
			fprintf(stderr, "strftime returned 0");
			exit(EXIT_FAILURE);
		}
		
		id = g_strdup_printf("%s.%d", outstr, n++);
	} while (option_get_string("network", id, "name"));

	gui_show_network_profile_editor(id, dialog_network_profiles);
}


void
on_network_profile_remove_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkTreeSelection *sel;
	GtkTreeModel *model;
	GtkTreeIter iter;
	GtkWidget *dialog;
	char *id = NULL, *name = NULL, *str;
	char *cat, *mod, *opt;
	int opt_iter;

	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(dialog_network_profiles, "treeview")));

	if (gtk_tree_selection_get_selected (sel, &model, &iter)) {
		gtk_tree_model_get(model, &iter, 0, &id, 1, &name, -1);

		str = g_strdup_printf(_("Opravdu chcete odstranit profil \"%s\"?"), name);
		dialog = gtk_message_dialog_new (GTK_WINDOW (main_window),
				GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
				GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE,
				str);
		g_free(str);
		str = g_strdup_printf(_("Bude nevratně vymazána veškerá konfigurace náležící tomuto profilu.\n\n"
					"ID profilu: %s"), id);
		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), str);
		g_free(str);
		gtk_window_set_transient_for(GTK_WINDOW(dialog), GTK_WINDOW(dialog_network_profiles));
		gtk_dialog_add_buttons(GTK_DIALOG(dialog), GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
				GTK_STOCK_REMOVE, GTK_RESPONSE_OK, NULL);

		if (gtk_dialog_run (GTK_DIALOG (dialog)) == GTK_RESPONSE_OK) {
			for (opt_iter = 0; option_list_opt("network", &opt_iter, &cat, &mod, &opt, NULL); opt_iter++) {
				if (strcmp(cat, "network") == 0 && strcmp(mod, id) == 0)
					option_unset_by_id(opt_iter);
			}
			gui_update_network_profiles();
		}
		
		gtk_widget_destroy (dialog);
	}
	
}


void
on_network_profile_config_clicked      (GtkButton       *button,
                                        gpointer         user_data)
{
	GtkTreeSelection *sel = NULL;
	GtkTreeModel *model = NULL;
	GtkTreeIter iter;
	char *id = NULL;

	sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(lookup_widget(dialog_network_profiles, "treeview")));

	if (gtk_tree_selection_get_selected(sel, &model, &iter)) {
		gtk_tree_model_get(model, &iter, 0, &id, -1);
		gui_show_network_backend_config(id);
	}
}


void
on_send_message_clear_clicked          (GtkButton       *button,
                                        gpointer         user_data)
{
	gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(lookup_widget(dialog_send_message, "body_textview"))), "", -1);
}


void
on_send_message_send_clicked           (GtkButton       *button,
                                        gpointer         user_data)
{
	gchar *body;
	int from, to;
	char *p = NULL;
	MESSAGE *msg;


	gui_dialog_send_message_get(&from, &to, &body);
	DBG_MSG(2, "from: %c, to: %c, message: \"%s\"", from, to, body);

	while ((msg = message_from_string(from, to, body, &p))) {
		char *msg_text;
		DBG_MSG(3, "mesage parsed");

		msg_text = message_to_string(msg, 0);
		gui_append_to_chat(NULL, GUI_CHAT_SYS, _("Posílám zprávu: %s"), msg_text);
		free(msg_text);

		message_send(msg);
		message_destroy(msg);
	}
	
	g_free(body);
}


void
on_dialog_send_message_destroy         (GtkObject       *object,
                                        gpointer         user_data)
{
	dialog_send_message = NULL;
}

void
on_dialog_send_message_body_changed    (GtkTextBuffer   *textbuffer,
                                        gpointer         user_data)
{
	if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(lookup_widget(dialog_send_message, "auto_update_togglebutton"))))
		on_dialog_send_message_update_now_clicked (NULL, NULL);
}


void
on_dialog_send_message_update_now_clicked (GtkButton       *button,
                                           gpointer         user_data)
{
	gchar *body;
	int from, to;
	char *p = NULL;
	MESSAGE *msg;

	gui_dialog_send_message_get(&from, &to, &body);
	DBG_MSG(6, "from: %c, to: %c, message: \"%s\"", from, to, body);
	
	gui_dialog_send_message_clear_message();
	while ((msg = message_from_string(from, to, body, &p))) {
		char *msg_text;
		DBG_MSG(6, "mesage parsed");

		msg_text = message_to_string(msg, 1);
		gui_dialog_send_message_add_message(msg_text);
		free(msg_text);

		message_destroy(msg);
	}
	g_free(body);
}


GTimer *debug_ping_timer[MESSAGE_MAX_TARGETS] = { };

static gboolean send_ping_timeout(gpointer userdata)
{
	int target = GPOINTER_TO_UINT(userdata);

	if (debug_ping_timer[target]) {
		gui_append_to_chat(NULL, GUI_CHAT_SYS, "No ping reply from \"%s\" in 0.5 seconds.",
				message_get_target_description(target));
		g_timer_destroy(debug_ping_timer[target]);
		debug_ping_timer[target] = NULL;
	}

	return FALSE;
}

static void send_ping(int target) 
{
	MESSAGE *msg;

	assert(target < MESSAGE_MAX_TARGETS);
	
	if (!debug_ping_timer[target]) {
		g_timeout_add(1000, send_ping_timeout, GUINT_TO_POINTER(target));
		debug_ping_timer[target] = g_timer_new();
		msg = message_create('T', target);
		message_append(msg, MESSAGE_PART_DATA, MESSAGE_STRING, "Tp", MESSAGE_END);
		message_send(msg);
		message_destroy(msg);
	}
}

static gboolean send_ping_later(gpointer userdata)
{
	static int i = 0, loop = 0;
	char target[] = { 'G', 'N', 0 };

	if (target[i]) {
		gui_append_to_chat(NULL, GUI_CHAT_SYS, "Pinging to \"%s\" ...", message_get_target_description(target[i]));
		send_ping(target[i]);
		i++;
		return TRUE;
	} else {
		i = 0;
		if (loop < option_get_integer("main", "debug", "ping_loops")) {
			gui_append_to_chat(NULL, GUI_CHAT_SYS, "Loop %d ...", loop + 2);
			loop++;
			return TRUE;
		} else {
			gui_append_to_chat(NULL, GUI_CHAT_SYS, "Ping test done.", loop);
			loop = 0;
			return FALSE;
		}
	}
	
}

static void debug_timer_test (unsigned long len)
{
	GTimer *timer;
	gulong usec, sec;
	struct timeval tv;

	/* init */
	tv.tv_sec  = len / 1000000;
	tv.tv_usec = len % 1000000;
	
	/* timer start */
	timer = g_timer_new();
	g_timer_start(timer);
	
	/* delay */
	while (select(0, NULL, NULL, NULL, &tv) != 0)
		;

	/* timer stop */
	g_timer_stop(timer);
	sec = g_timer_elapsed(timer, &usec);
	g_timer_destroy(timer);

	/* show result */
	gui_append_to_chat(NULL, GUI_CHAT_SYS,
			"GTimer: %lu usec = %lu sec %lu usec ... error: %0.3f %%",
			len, sec, usec, (float)(sec * 1e6 + usec - len) / (float) len * 100);
}

void
on_debug_ping_activate                 (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{
	
	if (option_get_integer("main", "debug", "do_timer_test")) {
		gui_append_to_chat(NULL, GUI_CHAT_SYS, "Timer test:");
		debug_timer_test(10);
		debug_timer_test(100);
		debug_timer_test(1000);
		debug_timer_test(10000);
		debug_timer_test(100000);
	}
	gui_append_to_chat(NULL, GUI_CHAT_SYS, "Ping test:");
	g_timeout_add(550, send_ping_later, NULL);
}

