/* $Id: keyb.c,v 1.4 2004/05/20 16:55:30 stpohle Exp $
 * keyb.c
 */

#include "bomberclone.h"
#include "network.h"
#include "ogcache-client.h"
#include "menu.h"
#include "keyb.h"

BCGameKeys keyb_gamekeys;

/*
 * Translation table for the keycodes 
 */
const struct _key_codes key_codetab [] = {
	{ SDLK_RSHIFT, "RSHIFT" },
	{ SDLK_LSHIFT, "LSHIFT" },
	{ SDLK_RCTRL, "RCTRL" },
	{ SDLK_LCTRL, "LCTRL" },
	{ SDLK_UP, "CurUP" },
	{ SDLK_DOWN, "CurDOWN" },
	{ SDLK_LEFT, "CurLEFT" },
	{ SDLK_RIGHT, "CurRIGHT" },
	{ SDLK_F1, "F1" },
	{ SDLK_F2, "F2" },
	{ SDLK_F3, "F3" },
	{ SDLK_F4, "F4" },
	{ SDLK_F5, "F5" },
	{ SDLK_F6, "F6" },
	{ SDLK_F7, "F7" },
	{ SDLK_F8, "F8" },
	{ SDLK_F9, "F9" },
	{ SDLK_F10, "F10" },
	{ SDLK_F11, "F11" },
	{ SDLK_F12, "F12" },
	{ ' ', "SPACE" },
	{ -1, "" }
};


/*
 * set the default keyboard settings
 */
void keyb_config_reset () {
	/* player 1 */
	keyb_gamekeys.keycode[BCPK_up] = SDLK_UP;
	keyb_gamekeys.keycode[BCPK_down] = SDLK_DOWN;
	keyb_gamekeys.keycode[BCPK_left] = SDLK_LEFT;
	keyb_gamekeys.keycode[BCPK_right] = SDLK_RIGHT;
	keyb_gamekeys.keycode[BCPK_drop] = SDLK_RCTRL;
	keyb_gamekeys.keycode[BCPK_special] = SDLK_RSHIFT;

	/* player 2 */
	keyb_gamekeys.keycode[BCPK_max + BCPK_up] = 'W';
	keyb_gamekeys.keycode[BCPK_max + BCPK_down] = 'S';
	keyb_gamekeys.keycode[BCPK_max + BCPK_left] = 'A';
	keyb_gamekeys.keycode[BCPK_max + BCPK_right] = 'D';
	keyb_gamekeys.keycode[BCPK_max + BCPK_drop] = SDLK_LCTRL;
	keyb_gamekeys.keycode[BCPK_max + BCPK_special] = SDLK_LSHIFT;
	
	/* game keys */
	keyb_gamekeys.keycode[BCK_help] = SDLK_F1;
	keyb_gamekeys.keycode[BCK_playermenu] = SDLK_F2;
	keyb_gamekeys.keycode[BCK_mapmenu] = SDLK_F3;
	keyb_gamekeys.keycode[BCK_chat] = SDLK_F5;
	keyb_gamekeys.keycode[BCK_pause] = SDLK_F4;
	keyb_gamekeys.keycode[BCK_fullscreen] = SDLK_F8;
	keyb_gamekeys.keycode[BCK_esc] = SDLK_ESCAPE;
};



/*
 * only for debug reasons, print out the states of the keys
 */
void keyb_print () {
	int i;
	
	printf ("keyb_gamekeys.state/old : ");
	for (i = 0; i < BCK_max; i++)
		printf ("%1d%1d ", keyb_gamekeys.state[i], keyb_gamekeys.old[i]);
	printf ("\n");
};


/*
 * convert a keycode to a text
 */
void keyb_code2text (int keycode, char *keytext) {
	int i;
	
	for (i = 0; (key_codetab [i].code != -1 && key_codetab[i].code != keycode); i++);

	if (key_codetab[i].code == keycode)
		strcpy (keytext, key_codetab[i].text);
	else if ((keycode >= 'a' && keycode <= 'z')
			 || (keycode >= 'A' && keycode <= 'Z')
			 || (keycode >= '0' && keycode <= '9'))
		sprintf (keytext, "%c", keycode);
	else 
		sprintf (keytext, "%x", keycode);
};


/*
 * create a small menu with all informations
 */
void keyb_config_createkeymenu (_menu *menu, int key, int x, int y, int menu_nr) {
	int key_id;
	char keyname [32];
	char keytext [50];
	
	if (key >= BCPK_max && key < BCPK_max * 2) 
		key_id = key - BCPK_max;
	else key_id = key;
	
	switch (key_id) {
		case (BCPK_up):
			strcpy (keyname, "Up");
			break;
		case (BCPK_down):
			strcpy (keyname, "Down");
			break;
		case (BCPK_left):
			strcpy (keyname, "Left");
			break;
		case (BCPK_right):
			strcpy (keyname, "Right");
			break;
		case (BCPK_drop):
			strcpy (keyname, "Drop");
			break;
		case (BCPK_special):
			strcpy (keyname, "Special");
			break;
/*		case (BCK_chat):
			strcpy (keyname, "Chat");
			break;
		case (BCK_fullscreen):
			strcpy (keyname, "Fullscreen");
			break;
		case (BCK_help):
			strcpy (keyname, "Help");
			break;
		case (BCK_mapmenu):
			strcpy (keyname, "Mapmenu");
			break;
		case (BCK_playermenu):
			strcpy (keyname, "Playermenu");
			break;
		case (BCK_pause):
			strcpy (keyname, "Pause/Start");
			break; */
	}
	
	menu_create_label (menu, keyname, x, y + 2, 0, COLOR_brown);
	keyb_code2text (keyb_gamekeys.keycode[key], keytext);
	menu_create_button (menu, keytext, x + 50, y, 100, menu_nr + key);
}


/*
 * select a new key for the function, 
 */
void keyb_config_readkey (int key) {
	int newkey;
    SDL_Event event;
    Uint8 *keys;
    int keypressed = 0,
        done = 0,
        eventstate = 0,
        reorder = 0;
		newkey = 0;

	
	if (key < 0 || key >= BCK_max) 
		return;
	
	menu_displaytext ("Keyboard Config", "Please press the new key\nfor this function.");

    keys = SDL_GetKeyState (NULL);
    if (keys[SDLK_RETURN] || keys[SDLK_ESCAPE])
        keypressed = 1;

    timestamp = SDL_GetTicks (); // needed for time sync.

    while (!reorder && !done && bman.state != GS_quit) {
        /* do the network loop if we have to */
        if (bman.sock > 0) {
            network_loop ();
            if (bman.notifygamemaster)
                reorder = ogc_loop ();
            else
                reorder = 0;
        }

        eventstate = SDL_PollEvent (&event);

        if (eventstate >= 1) {
            switch (event.type) {
            case (SDL_QUIT):
                bman.state = GS_quit;
                done = 1;
                break;
            case (SDL_KEYDOWN): /* focus next element */
				newkey = event.key.keysym.sym;
				done = 1;
				break;
            }
        }

        s_calctimesync ();
    }
	
	if (newkey != 0 && newkey != SDLK_ESCAPE)
		keyb_gamekeys.keycode[key] = newkey;
};


/*
 * keyboard configuration screen
 */
void keyb_config () {
	int menuselect = 1;
	_menu *menu;
	
	do {
		menu = menu_new ("Keyboard Config", 420, 400);
		menu_create_label (menu, "Player 1", 10, 50, 2, COLOR_brown);
		keyb_config_createkeymenu (menu, BCPK_up, 25, 90, 10);
		keyb_config_createkeymenu (menu, BCPK_down, 25, 120, 10);
		keyb_config_createkeymenu (menu, BCPK_left, 25, 150, 10);
		keyb_config_createkeymenu (menu, BCPK_right, 25, 180, 10);
		keyb_config_createkeymenu (menu, BCPK_drop, 25, 210, 10);
		keyb_config_createkeymenu (menu, BCPK_special, 25, 240, 10);
	
		menu_create_label (menu, "Player 2", 200, 50, 2, COLOR_brown);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_up, 225, 90, 10);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_down, 225, 120, 10);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_left, 225, 150, 10);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_right, 225, 180, 10);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_drop, 225, 210, 10);
		keyb_config_createkeymenu (menu, BCPK_max + BCPK_special, 225, 240, 10);
	
		/*menu_create_label ("Other Keys", -1, 270, 2, COLOR_brown);
		keyb_config_createkeymenu (BCK_help, 25, 300, 10);
		keyb_config_createkeymenu (BCK_chat, 25, 330, 10);
		keyb_config_createkeymenu (BCK_fullscreen, 25, 360, 10);
		keyb_config_createkeymenu (BCK_mapmenu, 225, 300, 10);
		keyb_config_createkeymenu (BCK_playermenu, 225, 330, 10);
		keyb_config_createkeymenu (BCK_pause, 225, 360, 10); */
		
		menu_create_button (menu, "Default", 50, 280, 150, 2);
		menu_create_button (menu, "OK", 250, 280, 150, 1);
		menu_focus_id (menu, menuselect);
		menuselect = menu_loop (menu);
		menu_delete (menu);
		if (menuselect ==2)
			keyb_config_reset ();
		if (menuselect >= 10 && menuselect < 10+BCK_max)
			keyb_config_readkey (menuselect - 10);
	} while (menuselect != 1 && menuselect != -1);
};


/*
 * delete all old data of the keyb_gamekeys
 */
void keyb_init () {	
	memset (keyb_gamekeys.state, 0, sizeof (Uint8) * BCK_max);
};


/*
 * read all keys and set the keyb_gamekeys
 */
void keyb_loop (SDL_Event *event) {
	int i;
	
	Uint8 *keys = SDL_GetKeyState (NULL);
	
	/* copy the state into the old state */
	memcpy (keyb_gamekeys.old, keyb_gamekeys.state, sizeof (Uint8) * BCK_max);
	memset (keyb_gamekeys.state, 0, sizeof (Uint8) * BCK_max);

	/* read the new state of the pressed keys */
	for (i = 0; i < BCK_max; i++) {
		if (keyb_gamekeys.keycode[i] >= 'A' && keyb_gamekeys.keycode[i] <= 'Z') {
			if (keys[keyb_gamekeys.keycode[i]] || keys[tolower (keyb_gamekeys.keycode[i])])
				keyb_gamekeys.state[i] |= 1;
		}
		else if (keys[keyb_gamekeys.keycode[i]])
			keyb_gamekeys.state[i] |= 1;
	}
};
