/*
Copyright (C) 1997-2001 Id Software, Inc.

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.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/

#include "ui_local.h"

/*
=======================================================================

KEYS MENU

=======================================================================
*/
int				keys_cursor;
static int		bind_grab;

static menuframework_s	s_keys_menu;


// wsw : pb : automatic menu
#define KEYMENU_MAX_NAME	32
#define KEYMENU_MAX_TITLE	64

typedef struct 
{
	char		name[KEYMENU_MAX_NAME];
	char		title[KEYMENU_MAX_TITLE];
} KeyMenuItem;

static KeyMenuItem KMItems[]= 
{
	// Movement
	{"+forward", 				"walk forward"},
	{"+back", 					"backpedal"},
	{"+moveleft", 				"step left"},
	{"+moveright", 				"step right"},
	{"+strafe", 				"sidestep"},
	{"+speed", 					"run"},
	{"+moveup",					"up / jump"},
	{"+movedown",				"down / crouch"},
	{"+special", 				"dash / wj"},

	// Attack & Weapons
	{ "+attack",				"attack"},
	{"weapprev", 				"previous weapon"},
	{"weapnext", 				"next weapon"},
	{"drop weapon",				"drop weapon"},
	{"use Gunblade",			"use gunblade"},
	{"use Riotgun",				"use riotgun"},
	{"use Grenade Launcher",	"use grenade launcher"},
	{"use Rocket Launcher",		"use rocket launcher"},
	{"use Plasmagun",			"use plasmagun"},
	{"use LaserGun",			"use lasergun"},
	{"use Electrobolt",			"use electrobolt"},

	// Misc
	{"score",			"show score"},
	{"vote yes",		"vote yes"},
	{"vote no",			"vote no"},
	{"join",			"join"},
	{"ready",			"ready"},
	{"chase",			"chase cam"},
	{"messagemode",		"chat"},
	{"messagemode2",	"chat team"},
};

static int KM_NbItems= sizeof(KMItems)/sizeof(KeyMenuItem);
// wsw : pb : !automatic menu


static void M_UnbindCommand( char *command )
{
	int		j;
	int		l;
	char	*b;

	l = strlen( command );

	for( j = 0; j < 256; j++ )
	{
		b = trap_Key_GetBindingBuf(j);
		if( !b )
			continue;
		if( !Q_stricmp(b, command) )
			trap_Key_SetBinding( j, NULL );
	}
}

static void M_FindKeysForCommand( char *command, int *twokeys )
{
	int		count;
	int		j;
	int		l;
	char	*b;

	twokeys[0] = twokeys[1] = -1;
	l = strlen(command);
	count = 0;

	for (j=0 ; j<256 ; j++)
	{
		b = trap_Key_GetBindingBuf(j);
		if (!b)
			continue;
		if (!Q_stricmp (b, command) )
		{
			twokeys[count] = j;
			count++;
			if (count == 2)
				break;
		}
	}
}

static void KeyCursorDrawFunc( menuframework_s *menu )
{
	menucommon_t *item;
	struct mufont_s *font = uis.fontSystemSmall;
	int picsize = trap_SCR_strHeight( font );

	item = Menu_ItemAtCursor( menu );

	if ( bind_grab )
		trap_SCR_DrawString( menu->x + item->cursor_offset, menu->y + item->y, ALIGN_LEFT_TOP, "=", font, colorWhite );
	else {
		if( ( int ) ( uis.time / 250 ) & 1 ) {
			trap_R_DrawStretchPic( menu->x + item->cursor_offset, menu->y + item->y, picsize, picsize, 0, 0, 1, 1,
				colorWhite, trap_R_RegisterPic( "gfx/ui/arrow_right" ) );
		}
	}
}

static void DrawKeyBindingFunc( menucommon_t *menuitem )
{
	int keys[2];

	M_FindKeysForCommand( KMItems[menuitem->localdata[0]].name, keys );

	if (keys[0] == -1)
	{
		trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16,
			menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, "???", uis.fontSystemSmall, colorWhite );
	}
	else
	{
		int x;
		char *name;
		name = trap_Key_KeynumToString( keys[0] );

		trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16,
			menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, name, uis.fontSystemSmall, colorWhite );
		x = trap_SCR_strWidth( name, uis.fontSystemSmall, 0 );

		if (keys[1] != -1)
		{
			trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16 + 8 + x,
				menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, "or", uis.fontSystemSmall, colorWhite );

			trap_SCR_DrawString( menuitem->x + menuitem->parent->x + 16 + 8 + x + 8*3,
				menuitem->y + menuitem->parent->y, ALIGN_LEFT_TOP, trap_Key_KeynumToString(keys[1]), uis.fontSystemSmall, colorWhite );
		}
	}
}

static void KeyBindingFunc( menucommon_t *menuitem )
{
	int keys[2];

	M_FindKeysForCommand( KMItems[menuitem->localdata[0]].name, keys);

	if (keys[1] != -1)
		M_UnbindCommand( KMItems[menuitem->localdata[0]].name );

	bind_grab = qtrue;

	Menu_SetStatusBar( &s_keys_menu, "press a key or button for this action" );
}

static void Keys_MenuInit( void )
{
	int w, h;
	int y = 0;
	int i = 0;
	int yoffset = 0;
	menucommon_t *menuitem;

	w = uis.vidWidth;
	h = uis.vidHeight;

	s_keys_menu.x = w / 2;
	s_keys_menu.y = h / 2 - 80;
	s_keys_menu.nitems = 0;
	s_keys_menu.cursordraw = KeyCursorDrawFunc;

	for( i = 0; i < KM_NbItems; i++ )
	{
		menuitem = UI_InitMenuItem( KMItems[i].name, KMItems[i].title, 0, y+yoffset, MTYPE_ACTION, ALIGN_RIGHT_TOP, uis.fontSystemSmall, NULL );
		menuitem->localdata[0] = i;
		menuitem->ownerdraw = DrawKeyBindingFunc;
		Menu_AddItem( &s_keys_menu, menuitem );

		yoffset += trap_SCR_strHeight( menuitem->font );
	}

	Menu_Center( &s_keys_menu );
	Menu_Init( &s_keys_menu );

	Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
}

static void Keys_MenuDraw( void )
{
	Menu_AdjustCursor( &s_keys_menu, 1 );
	Menu_Draw( &s_keys_menu );
}

static const char *Keys_MenuKey( int key )
{
	menucommon_t *menuitem = Menu_ItemAtCursor( &s_keys_menu );

	if ( bind_grab )
	{	
		if ( key != K_ESCAPE && key != '`' )
		{
			char cmd[1024];

			Q_snprintfz (cmd, sizeof(cmd), "bind \"%s\" \"%s\"\n", trap_Key_KeynumToString(key), KMItems[menuitem->localdata[0]].name);
			trap_Cmd_ExecuteText (EXEC_INSERT, cmd);
		}
		
		Menu_SetStatusBar( &s_keys_menu, "enter to change, backspace to clear" );
		bind_grab = qfalse;
		return menu_out_sound;
	}

	switch ( key )
	{
	case KP_ENTER:
	case K_ENTER:
	case K_MOUSE1:
		KeyBindingFunc( menuitem );
		return menu_in_sound;
	case K_BACKSPACE:		// delete bindings
	case K_DEL:				// delete bindings
	case KP_DEL:
		M_UnbindCommand( KMItems[menuitem->localdata[0]].name );
		return menu_out_sound;
	default:
		return Default_MenuKey( &s_keys_menu, key );
	}
}

static const char *Keys_MenuCharEvent( int key )
{
	return Default_MenuCharEvent( &s_keys_menu, key );
}

void M_Menu_Keys_f( void )
{
	Keys_MenuInit();
	M_PushMenu( &s_keys_menu, Keys_MenuDraw, Keys_MenuKey, Keys_MenuCharEvent );
}
