/*
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 "extdll.h"
#include "basemenu.h"
#include "utils.h"
#include "keydefs.h"
#include "menu_btnsbmp_table.h"

#define ART_BANNER		"gfx/shell/head_inetgames"

#define ID_BACKGROUND	0
#define ID_BANNER		1
#define ID_JOINGAME		2
#define ID_CREATEGAME	3
#define ID_GAMEINFO		4
#define ID_REFRESH		5
#define ID_DONE		6
#define ID_SERVERSLIST	7
#define ID_TABLEHINT	8

#define ID_MSGBOX	 	9
#define ID_MSGTEXT	 	10
#define ID_YES	 	130
#define ID_NO	 	131

#define GAME_LENGTH		28
#define MAPNAME_LENGTH	20+GAME_LENGTH
#define TYPE_LENGTH		10+MAPNAME_LENGTH
#define MAXCL_LENGTH	15+TYPE_LENGTH

typedef struct
{
	char		gameDescription[UI_MAX_SERVERS][256];
	char		*gameDescriptionPtr[UI_MAX_SERVERS];

	menuFramework_s	menu;

	menuBitmap_s	background;
	menuBitmap_s	banner;
	menuPicButton_s	joinGame;
	menuPicButton_s	createGame;
	menuPicButton_s	gameInfo;
	menuPicButton_s	refresh;
	menuPicButton_s	done;

	// joingame prompt dialog
	menuAction_s	msgBox;
	menuAction_s	dlgMessage1;
	menuAction_s	dlgMessage2;
	menuPicButton_s	yes;
	menuPicButton_s	no;

	menuScrollList_s	gameList;
	menuAction_s	hintMessage;
	char		hintText[MAX_HINT_TEXT];
	int		refreshTime;
} uiInternetGames_t;

static uiInternetGames_t	uiInternetGames;

static void UI_PromptDialog( void )
{
	// toggle main menu between active\inactive
	// show\hide quit dialog
	uiInternetGames.joinGame.generic.flags ^= QMF_INACTIVE; 
	uiInternetGames.createGame.generic.flags ^= QMF_INACTIVE;
	uiInternetGames.gameInfo.generic.flags ^= QMF_INACTIVE;
	uiInternetGames.refresh.generic.flags ^= QMF_INACTIVE;
	uiInternetGames.done.generic.flags ^= QMF_INACTIVE;
	uiInternetGames.gameList.generic.flags ^= QMF_INACTIVE;

	uiInternetGames.msgBox.generic.flags ^= QMF_HIDDEN;
	uiInternetGames.dlgMessage1.generic.flags ^= QMF_HIDDEN;
	uiInternetGames.dlgMessage2.generic.flags ^= QMF_HIDDEN;
	uiInternetGames.no.generic.flags ^= QMF_HIDDEN;
	uiInternetGames.yes.generic.flags ^= QMF_HIDDEN;

}

/*
=================
UI_InternetGames_KeyFunc
=================
*/
static const char *UI_InternetGames_KeyFunc( int key, int down )
{
	if( down && key == K_ESCAPE && !( uiInternetGames.dlgMessage1.generic.flags & QMF_HIDDEN ))
	{
		UI_PromptDialog();
		return uiSoundNull;
	}
	return UI_DefaultKey( &uiInternetGames.menu, key, down );
}

/*
=================
UI_InternetGames_GetGamesList
=================
*/
static void UI_InternetGames_GetGamesList( void )
{
	int		i;
	const char	*info, *host, *map;
	int		colorOffset[2];

	for( i = 0; i < uiStatic.numServers; i++ )
	{
		if( i >= UI_MAX_SERVERS ) break;
		info = uiStatic.serverNames[i];

		host = Info_ValueForKey( info, "host" );
		colorOffset[0] = ColorPrexfixCount( host );
		StringConcat( uiInternetGames.gameDescription[i], host, GAME_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, GAME_LENGTH + colorOffset[0] );
		map = Info_ValueForKey( info, "map" );
		colorOffset[1] = ColorPrexfixCount( map );
		StringConcat( uiInternetGames.gameDescription[i], map, MAPNAME_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, MAPNAME_LENGTH + colorOffset[0] + colorOffset[1] );
		if( !strcmp( Info_ValueForKey( info, "dm" ), "1" ))
			StringConcat( uiInternetGames.gameDescription[i], "dm", TYPE_LENGTH );
		else if( !strcmp( Info_ValueForKey( info, "coop" ), "1" ))
			StringConcat( uiInternetGames.gameDescription[i], "coop", TYPE_LENGTH );
		else if( !strcmp( Info_ValueForKey( info, "team" ), "1" ))
			StringConcat( uiInternetGames.gameDescription[i], "team", TYPE_LENGTH );
		else StringConcat( uiInternetGames.gameDescription[i], "???", TYPE_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, TYPE_LENGTH + colorOffset[0] + colorOffset[1] );
		StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "numcl" ), MAXCL_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], "\\", MAXCL_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], Info_ValueForKey( info, "maxcl" ), MAXCL_LENGTH );
		StringConcat( uiInternetGames.gameDescription[i], uiEmptyString, MAXCL_LENGTH );
		uiInternetGames.gameDescriptionPtr[i] = uiInternetGames.gameDescription[i];
	}

	for( ; i < UI_MAX_SERVERS; i++ )
		uiInternetGames.gameDescriptionPtr[i] = NULL;

	uiInternetGames.gameList.itemNames = (const char **)uiInternetGames.gameDescriptionPtr;
	uiInternetGames.gameList.numItems = 0; // reset it

	if( !uiInternetGames.gameList.generic.charHeight )
		return; // to avoid divide integer by zero

	// count number of items
	while( uiInternetGames.gameList.itemNames[uiInternetGames.gameList.numItems] )
		uiInternetGames.gameList.numItems++;

	// calculate number of visible rows
	uiInternetGames.gameList.numRows = (uiInternetGames.gameList.generic.height2 / uiInternetGames.gameList.generic.charHeight) - 2;
	if( uiInternetGames.gameList.numRows > uiInternetGames.gameList.numItems ) uiInternetGames.gameList.numRows = uiInternetGames.gameList.numItems;

	if( uiStatic.numServers )
		uiInternetGames.joinGame.generic.flags &= ~QMF_GRAYED;
}

/*
=================
UI_InternetGames_JoinGame
=================
*/
static void UI_InternetGames_JoinGame( void )
{
	if( !strlen( uiInternetGames.gameDescription[uiInternetGames.gameList.curItem] ))
		return;

	CLIENT_JOIN( uiStatic.serverAddresses[uiInternetGames.gameList.curItem] );
}

/*
=================
UI_Background_Ownerdraw
=================
*/
static void UI_Background_Ownerdraw( void *self )
{
	menuCommon_s	*item = (menuCommon_s *)self;

	if( !CVAR_GET_FLOAT( "cl_background" ))
		UI_DrawBackground_Callback( self );

	if( uiStatic.realTime > uiInternetGames.refreshTime )
	{
		uiInternetGames.refreshTime = uiStatic.realTime + 10000; // refresh every 10 secs
		UI_RefreshInternetServerList();
	}

	// serverinfo has been changed update display
	if( uiStatic.updateServers )
	{
		UI_InternetGames_GetGamesList ();
		uiStatic.updateServers = false;
	}
}

/*
=================
UI_MsgBox_Ownerdraw
=================
*/
static void UI_MsgBox_Ownerdraw( void *self )
{
	menuCommon_s	*item = (menuCommon_s *)self;

	UI_FillRect( item->x, item->y, item->width, item->height, uiPromptBgColor );
}

/*
=================
UI_InternetGames_Callback
=================
*/
static void UI_InternetGames_Callback( void *self, int event )
{
	menuCommon_s	*item = (menuCommon_s *)self;

	if( event != QM_ACTIVATED )
		return;

	switch( item->id )
	{
	case ID_JOINGAME:
		if( CL_IsActive( ))
			UI_PromptDialog();
		else UI_InternetGames_JoinGame();
		break;
	case ID_CREATEGAME:
		CVAR_SET_FLOAT( "public", 1.0f );
		UI_CreateGame_Menu();
		break;
	case ID_GAMEINFO:
		// UNDONE: not implemented
		break;
	case ID_REFRESH:
		UI_RefreshInternetServerList();
		break;
	case ID_DONE:
		UI_PopMenu();
		break;
	case ID_YES:
		UI_InternetGames_JoinGame();
		break;
	case ID_NO:
		UI_PromptDialog();
		break;
	}
}

/*
=================
UI_InternetGames_Init
=================
*/
static void UI_InternetGames_Init( void )
{
	memset( &uiInternetGames, 0, sizeof( uiInternetGames_t ));

	uiInternetGames.menu.vidInitFunc = UI_InternetGames_Init;
	uiInternetGames.menu.keyFunc = UI_InternetGames_KeyFunc;

	StringConcat( uiInternetGames.hintText, "Game", GAME_LENGTH );
	StringConcat( uiInternetGames.hintText, uiEmptyString, GAME_LENGTH );
	StringConcat( uiInternetGames.hintText, "Map", MAPNAME_LENGTH );
	StringConcat( uiInternetGames.hintText, uiEmptyString, MAPNAME_LENGTH );
	StringConcat( uiInternetGames.hintText, "Type", TYPE_LENGTH );
	StringConcat( uiInternetGames.hintText, uiEmptyString, TYPE_LENGTH );
	StringConcat( uiInternetGames.hintText, "Clients", MAXCL_LENGTH );
	StringConcat( uiInternetGames.hintText, uiEmptyString, MAXCL_LENGTH );

	uiInternetGames.background.generic.id = ID_BACKGROUND;
	uiInternetGames.background.generic.type = QMTYPE_BITMAP;
	uiInternetGames.background.generic.flags = QMF_INACTIVE;
	uiInternetGames.background.generic.x = 0;
	uiInternetGames.background.generic.y = 0;
	uiInternetGames.background.generic.width = 1024;
	uiInternetGames.background.generic.height = 768;
	uiInternetGames.background.pic = ART_BACKGROUND;
	uiInternetGames.background.generic.ownerdraw = UI_Background_Ownerdraw;

	uiInternetGames.banner.generic.id = ID_BANNER;
	uiInternetGames.banner.generic.type = QMTYPE_BITMAP;
	uiInternetGames.banner.generic.flags = QMF_INACTIVE|QMF_DRAW_ADDITIVE;
	uiInternetGames.banner.generic.x = UI_BANNER_POSX;
	uiInternetGames.banner.generic.y = UI_BANNER_POSY;
	uiInternetGames.banner.generic.width = UI_BANNER_WIDTH;
	uiInternetGames.banner.generic.height = UI_BANNER_HEIGHT;
	uiInternetGames.banner.pic = ART_BANNER;

	uiInternetGames.joinGame.generic.id = ID_JOINGAME;
	uiInternetGames.joinGame.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.joinGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED;
	uiInternetGames.joinGame.generic.x = 72;
	uiInternetGames.joinGame.generic.y = 230;
	uiInternetGames.joinGame.generic.name = "Join game";
	uiInternetGames.joinGame.generic.statusText = "Join to selected game";
	uiInternetGames.joinGame.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.joinGame, PC_JOIN_GAME );

	uiInternetGames.createGame.generic.id = ID_CREATEGAME;
	uiInternetGames.createGame.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.createGame.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
	uiInternetGames.createGame.generic.x = 72;
	uiInternetGames.createGame.generic.y = 280;
	uiInternetGames.createGame.generic.name = "Create game";
	uiInternetGames.createGame.generic.statusText = "Create new Internet game";
	uiInternetGames.createGame.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.createGame, PC_CREATE_GAME );

	uiInternetGames.gameInfo.generic.id = ID_GAMEINFO;
	uiInternetGames.gameInfo.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.gameInfo.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW|QMF_GRAYED;
	uiInternetGames.gameInfo.generic.x = 72;
	uiInternetGames.gameInfo.generic.y = 330;
	uiInternetGames.gameInfo.generic.name = "View game info";
	uiInternetGames.gameInfo.generic.statusText = "Get detail game info";
	uiInternetGames.gameInfo.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.gameInfo, PC_VIEW_GAME_INFO );

	uiInternetGames.refresh.generic.id = ID_REFRESH;
	uiInternetGames.refresh.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.refresh.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
	uiInternetGames.refresh.generic.x = 72;
	uiInternetGames.refresh.generic.y = 380;
	uiInternetGames.refresh.generic.name = "Refresh";
	uiInternetGames.refresh.generic.statusText = "Refresh servers list";
	uiInternetGames.refresh.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.refresh, PC_REFRESH );

	uiInternetGames.done.generic.id = ID_DONE;
	uiInternetGames.done.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.done.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_DROPSHADOW;
	uiInternetGames.done.generic.x = 72;
	uiInternetGames.done.generic.y = 430;
	uiInternetGames.done.generic.name = "Done";
	uiInternetGames.done.generic.statusText = "Return to main menu";
	uiInternetGames.done.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.done, PC_DONE );

	uiInternetGames.msgBox.generic.id = ID_MSGBOX;
	uiInternetGames.msgBox.generic.type = QMTYPE_ACTION;
	uiInternetGames.msgBox.generic.flags = QMF_INACTIVE|QMF_HIDDEN;
	uiInternetGames.msgBox.generic.ownerdraw = UI_MsgBox_Ownerdraw; // just a fill rectangle
	uiInternetGames.msgBox.generic.x = 192;
	uiInternetGames.msgBox.generic.y = 256;
	uiInternetGames.msgBox.generic.width = 640;
	uiInternetGames.msgBox.generic.height = 256;

	uiInternetGames.dlgMessage1.generic.id = ID_MSGTEXT;
	uiInternetGames.dlgMessage1.generic.type = QMTYPE_ACTION;
	uiInternetGames.dlgMessage1.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW;
	uiInternetGames.dlgMessage1.generic.name = "Join a network game will exit";
	uiInternetGames.dlgMessage1.generic.x = 248;
	uiInternetGames.dlgMessage1.generic.y = 280;

	uiInternetGames.dlgMessage2.generic.id = ID_MSGTEXT;
	uiInternetGames.dlgMessage2.generic.type = QMTYPE_ACTION;
	uiInternetGames.dlgMessage2.generic.flags = QMF_INACTIVE|QMF_HIDDEN|QMF_DROPSHADOW;
	uiInternetGames.dlgMessage2.generic.name = "any current game, OK to exit?";
	uiInternetGames.dlgMessage2.generic.x = 248;
	uiInternetGames.dlgMessage2.generic.y = 310;

	uiInternetGames.yes.generic.id = ID_YES;
	uiInternetGames.yes.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.yes.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW;
	uiInternetGames.yes.generic.name = "Ok";
	uiInternetGames.yes.generic.x = 380;
	uiInternetGames.yes.generic.y = 460;
	uiInternetGames.yes.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.yes, PC_OK );

	uiInternetGames.no.generic.id = ID_NO;
	uiInternetGames.no.generic.type = QMTYPE_BM_BUTTON;
	uiInternetGames.no.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_HIDDEN|QMF_DROPSHADOW;
	uiInternetGames.no.generic.name = "Cancel";
	uiInternetGames.no.generic.x = 530;
	uiInternetGames.no.generic.y = 460;
	uiInternetGames.no.generic.callback = UI_InternetGames_Callback;

	UI_UtilSetupPicButton( &uiInternetGames.no, PC_CANCEL );

	uiInternetGames.hintMessage.generic.id = ID_TABLEHINT;
	uiInternetGames.hintMessage.generic.type = QMTYPE_ACTION;
	uiInternetGames.hintMessage.generic.flags = QMF_INACTIVE|QMF_SMALLFONT;
	uiInternetGames.hintMessage.generic.color = uiColorHelp;
	uiInternetGames.hintMessage.generic.name = uiInternetGames.hintText;
	uiInternetGames.hintMessage.generic.x = 360;
	uiInternetGames.hintMessage.generic.y = 225;

	uiInternetGames.gameList.generic.id = ID_SERVERSLIST;
	uiInternetGames.gameList.generic.type = QMTYPE_SCROLLLIST;
	uiInternetGames.gameList.generic.flags = QMF_HIGHLIGHTIFFOCUS|QMF_SMALLFONT;
	uiInternetGames.gameList.generic.x = 360;
	uiInternetGames.gameList.generic.y = 255;
	uiInternetGames.gameList.generic.width = 640;
	uiInternetGames.gameList.generic.height = 440;
	uiInternetGames.gameList.generic.callback = UI_InternetGames_Callback;
	uiInternetGames.gameList.itemNames = (const char **)uiInternetGames.gameDescriptionPtr;

	// server.dll needs for reading savefiles or startup newgame
	if( !CheckGameDll( ))
		uiInternetGames.createGame.generic.flags |= QMF_GRAYED;	// server.dll is missed - remote servers only

	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.background );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.banner );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.joinGame );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.createGame );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.gameInfo );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.refresh );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.done );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.hintMessage );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.gameList );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.msgBox );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.dlgMessage1 );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.dlgMessage2 );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.no );
 	UI_AddItem( &uiInternetGames.menu, (void *)&uiInternetGames.yes );

	uiInternetGames.refreshTime = uiStatic.realTime + 500; // delay before update 0.5 sec
}

/*
=================
UI_InternetGames_Precache
=================
*/
void UI_InternetGames_Precache( void )
{
	PIC_Load( ART_BACKGROUND );
	PIC_Load( ART_BANNER );
}

/*
=================
UI_InternetGames_Menu
=================
*/
void UI_InternetGames_Menu( void )
{
	if ( gMenu.m_gameinfo.gamemode == GAME_SINGLEPLAYER_ONLY )
		return;

	// stop demos to allow open network sockets
	if ( gpGlobals->demoplayback && CVAR_GET_FLOAT( "cl_background" ))
	{
		uiStatic.m_iOldMenuDepth = uiStatic.menuDepth;
		CLIENT_COMMAND( FALSE, "stop\n" );
		uiStatic.m_fDemosPlayed = true;
	}

	UI_InternetGames_Precache();
	UI_InternetGames_Init();

	UI_PushMenu( &uiInternetGames.menu );
}