#include "AdeptHeaders.hpp"
#include "GameSpy.h"
#include <gameOS/GUNGameList.h>
#include "buildnum/buildnum.h"
#pragma comment(lib, "wsock32")

#ifndef NEW_GAMESPY

/******
goasample.c
GameSpy Developer SDK Sample App

Copyright 1999 GameSpy Industries, Inc

Suite E-204
2900 Bristol Street
Costa Mesa, CA 92626
(714)549-7689
Fax(714)549-0757

******

 This source file includes a "sample" game shell which demonstrates
 how to use the GameSpy Developer SDK (goautil.h)

 Please see the  GameSpy Developer SDK documentation for more
 information

******/

#define FixSZString(s) ((s)[sizeof(s)-1]) = 0

namespace GameSpyOld
{
	bool	bGameSpy;
};

/********
INCLUDES
********/
#include "nonport.h"
#include "goautil.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <conio.h>

/********
DEFINES
********/
#define GAME_VERSION CURRENT_BUILD_FULL_STRING
#define GAME_NAME GAMESPY_MASTER_ENGINENAME
#define MAX_PLAYERS 32

#ifdef _WIN32_WCE
void RetailOutputA(CHAR *tszErr, ...);
#define printf RetailOutputA
#endif


/********
TYPDEFS
********/
//representative of a game player structure
typedef struct
{
	char pname[80];
	char pteam[80];
	int id;
} player_t;

//representative of a game data structure
typedef struct
{
	player_t	players[MAX_PLAYERS];
	char		gamename[50];
	char		mapname[20];
	char		hostname[120];
	char		gamemode[200];
	char		gametype[30];
	GUID		guid;
	int			locationid;
	int			numplayers;
	int			maxplayers;
	int			fraglimit;
	int			timelimit;
	int			teamplay;
	int			rankingson;
	int			hostport;
	int			flags;
} gamedata_t;

/********
GLOBAL VARS
********/

//just to give us bogus data
char *constnames[MAX_PLAYERS]={"Joe Player","L33t 0n3","Raptor","Gr81","Flubber","Sarge","Void","runaway","Ph3ar","wh00t","gr1nder","Mace","stacy","lamby","Thrush"};
gamedata_t gamedata;


/*************
basic_callback
sends a (sample) response to the basic query
includes the following keys:
\gamename\
\gamever\
\location\
*************/
static void basic_callback(char *outbuf, int maxlen, void *userdata)
{
	sprintf(outbuf, "\\%s\\%s\\%s\\%s\\%s\\%d",
		GAMESPY_KEY_GAME_NAME, gamedata.gamename,
		GAMESPY_KEY_PRODUCT_VERSION, GAME_VERSION,
		GAMESPY_KEY_LOCATION, gamedata.locationid);

//	printf("Basic callback, sent: %s\n",outbuf);
}

/************
info_callback
Sends a (sample) response to the info query
including the following keys:
\hostname\
\hostport\
\mapname\
\gametype\
\numplayers\
\maxplayers\
\gamemode\
************/
static void info_callback(char *outbuf, int maxlen, void *userdata)
{
	char keyvalue[200];

	sprintf(keyvalue,"\\%s\\%s", GAMESPY_KEY_HOSTNAME, gamedata.hostname);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_HOSTPORT, gamedata.hostport);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%s", GAMESPY_KEY_MAP_TYPE, gamedata.mapname);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%s", GAMESPY_KEY_GAME_TYPE, gamedata.gametype);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_NUM_PLAYERS, gamedata.numplayers);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_MAX_PLAYERS, gamedata.maxplayers);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%s", GAMESPY_KEY_GAMEMODE, gamedata.gamemode);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_FLAGS, gamedata.flags);strcat(outbuf, keyvalue);
	sprintf(keyvalue,"\\%s\\{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}", GAMESPY_KEY_INSTANCE,
		gamedata.guid.Data1,
		gamedata.guid.Data2,
		gamedata.guid.Data3,
		gamedata.guid.Data4[0],
		gamedata.guid.Data4[1],
		gamedata.guid.Data4[2],
		gamedata.guid.Data4[3],
		gamedata.guid.Data4[4],
		gamedata.guid.Data4[5],
		gamedata.guid.Data4[6],
		gamedata.guid.Data4[7]);strcat(outbuf, keyvalue);

//	printf("Info callback, sent: %s\n",outbuf);

}

/***************
rules_callback
Sends a response to the rules query. You may
need to add custom fields for your game in here. Some are provided
as an example
The following rules are included:
\timelimit\
\fraglimit\
\teamplay\
\rankedserver\
****************/
static void rules_callback(char *outbuf, int maxlen, void *userdata)
{
//	char keyvalue[80];

//	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_TIMELIMIT, gamedata.timelimit);strcat(outbuf, keyvalue);
//	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_FRAGLIMIT, gamedata.fraglimit);strcat(outbuf, keyvalue);
//	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_TEAMPLAY, gamedata.teamplay);strcat(outbuf, keyvalue);

//	//sample custom key/value
//	sprintf(keyvalue,"\\%s\\%d", GAMESPY_KEY_RANKEDSERVER, gamedata.rankingson);strcat(outbuf, keyvalue);
//	printf("Rules callback, sent: %s\n",outbuf);

}

/***************
players_callback
sends the players and their information.
Note that \ characters are not stripped out of player names. If
your game allows players or team names with the \ character, you will need
to strip or change it here.
The following keys are included for each player:
\player_N\
\frags_N\
\deaths_N\
\skill_N\
\ping_N\
\team_N\
***************/
static void players_callback(char *outbuf, int maxlen, void *userdata)
{
	char keyvalue[160];
	int i;

	for (i = 0; i < gamedata.numplayers ; i++)
	{
		sprintf(keyvalue,
			"\\player_%d\\%s\\team_%d\\%s",
			i, gamedata.players[i].pname,
			i, gamedata.players[i].pteam);

		strcat(outbuf, keyvalue);
	}
	//printf("Players callback, sent: %s\n",outbuf);

}


/////***********
////init_game
////Initialize the sample data structures with bogus data
////************/
////static void init_game(void)
////{
////	int i;
////	int team;
////
////	srand( current_time() );
////	gamedata.numplayers = rand() % 15;
////	gamedata.maxplayers = MAX_PLAYERS;
////	for (i = 0 ; i < gamedata.numplayers ; i++)
////	{
////		strcpy(gamedata.players[i].pname, constnames[i]);
////		gamedata.players[i].pfrags = rand() % 32;
////		gamedata.players[i].pdeaths = rand() % 32;
////		gamedata.players[i].pskill = rand() % 1000;
////		gamedata.players[i].pping = rand() % 500;
////		team = rand() % 3;
////		if (team == 0)
////			strcpy(gamedata.players[i].pteam,"Red");
////		else if (team == 1)
////			strcpy(gamedata.players[i].pteam,"Blue");
////		else if (team == 2)
////			strcpy(gamedata.players[i].pteam,"");
////	}
////	strcpy(gamedata.mapname,"gmtmap1");
////	strcpy(gamedata.gametype,"arena");
////	strcpy(gamedata.hostname,"GameMaster Arena Server");
////	strcpy(gamedata.gamemode,"openplaying");
////	gamedata.fraglimit = 0;
////	gamedata.timelimit = 40;
////	gamedata.teamplay = 1;
////	gamedata.locationid = 1;
////	gamedata.rankingson = 1;
////	gamedata.hostport = 25000;
////}

/*******
 DoGameStuff
Simulate whatever else a game server does
********/
void DoGameStuff(void)
{
	msleep(10);
}

/////*******************
//// main
////Simulates a main program loop
////First, initializes the GOA items, then enters a main loop
////*****************/
////int main_1(int argc, char* argv[])
////{
////	//set the callback functions
////	goa_basic_callback = basic_callback;
////	goa_info_callback = info_callback;
////	goa_rules_callback = rules_callback;
////	goa_players_callback = players_callback;
////	//set the secret key, in a semi-obfuscated manner
////
////#if 0
////	goa_secret_key[0] = 'H';
////	goa_secret_key[1] = 'A';
////	goa_secret_key[2] = '6';
////	goa_secret_key[3] = 'z';
////	goa_secret_key[4] = 'k';
////	goa_secret_key[5] = 'S';
////	goa_secret_key[6] = '\0';
////#endif
////	init_game();
////
////	//call goa_init with the query port number and gamename, default IP address, and no user data
////	if (goa_init(27950,GAME_NAME, "localhost", NULL) != 0)
////	{
////		fprintf(stderr,"Error starting query sockets\n");
////		return -1;
////	}
////
////	while (kbhit())
////		_getch();
////
////	printf("Press any key to quit\n");
////	while (!kbhit())
////	{
////		DoGameStuff();
////		//check for / process incoming queries
////		goa_process_queries();
////
////	}
////	_getch();
////
////	//let gamemaster know we are shutting down
////	strcpy(gamedata.gamemode,"exiting");
////	goa_send_statechanged();
////	goa_shutdown();
////
////	return 0;
////
////}

//========================================================================
//========================================================================
bool GameSpyOld::BeginAdvertisingOnGameSpy(const char * GameName, const char *PlayerName, int MaxPlayers, const char *Password, const GUID &guidInstance, bool Secure, DWORD dwFlags)
{
	EndAdvertisingOnGameSpy();
	gosASSERT(GameName != NULL);
#ifdef _DEBUG
	if (!GameName)
		GameName = "testgame";
#endif

	strcpy(goa_secret_key, GetKeyName());

	//set the callback functions
	goa_basic_callback = basic_callback;
	goa_info_callback = info_callback;
	goa_rules_callback = rules_callback;
	goa_players_callback = players_callback;

	//init_game();

	strncpy(gamedata.players[0].pname, PlayerName, sizeof(gamedata.players[0].pname));
	strncpy(gamedata.gamename, GameName, sizeof(gamedata.gamename));
	//strncpy(gamedata.gametype, Environment.applicationName, sizeof(gamedata.gametype));

	FixSZString(gamedata.players[0].pname);
	FixSZString(gamedata.gamename);
	//FixSZString(gamedata.gametype);

	//strncpy(gamedata.mapname, "map", sizeof(gamedata.mapname));
	//strncpy(gamedata.hostname, GameName, sizeof(gamedata.hostname));

	gamedata.numplayers = 1;
	gamedata.maxplayers = MaxPlayers;
	gamedata.guid = guidInstance;
	gamedata.flags = dwFlags;

	//call goa_init with the query port number and gamename, default IP address, and no user data
	if (goa_init(GetQueryPort(), GAMESPY_MASTER_ENGINENAME, "localhost", NULL) != 0)
	{
		return false;
	}

	bGameSpy = true;

	return true;
}

//========================================================================
//========================================================================
void GameSpyOld::SetKey(const char *szKey, const char *szValue)
{
	if (!strcmp(szKey, GAMELIST_KEY_MAP_TYPE))
	{
		strcpy(gamedata.mapname, szValue);
	}
	if (!strcmp(szKey, GAMELIST_KEY_GAME_TYPE))
	{
		strcpy(gamedata.gametype, szValue);
	}
	goa_send_statechanged();
}

//========================================================================
//========================================================================
void GameSpyOld::EndAdvertisingOnGameSpy(void)
{
	if (bGameSpy)
	{
		goa_send_statechanged();
		goa_shutdown();
		bGameSpy = false;
	}

	return;
}

//========================================================================
//========================================================================
bool GameSpyOld::AddPlayer(int id, const char *szName, const char *szTeam, int reserved)
{
	if (gamedata.numplayers == MAX_PLAYERS)
		return false;

	if (szName)
	{
		strncpy(gamedata.players[gamedata.numplayers].pname, szName, sizeof(gamedata.players[gamedata.numplayers].pname));
		gamedata.players[gamedata.numplayers].pname[sizeof(gamedata.players[gamedata.numplayers].pname)-1]=0;
	}
	else
		gamedata.players[gamedata.numplayers].pname[0]=0;

	if (szTeam)
	{
		strncpy(gamedata.players[gamedata.numplayers].pteam, szTeam, sizeof(gamedata.players[gamedata.numplayers].pteam));
		gamedata.players[gamedata.numplayers].pteam[sizeof(gamedata.players[gamedata.numplayers].pteam)-1]=0;
	}
	else
		gamedata.players[gamedata.numplayers].pteam[0]=0;

	gamedata.players[gamedata.numplayers].id = id;
	gamedata.numplayers++;
	goa_send_statechanged();

	return true;
}

//========================================================================
//========================================================================
bool GameSpyOld::RemovePlayer(int id, const char *szName, const char *szTeam, int reserved)
{
	int i;
	for (i=0 ; i<gamedata.numplayers ; i++)
	{
		if (gamedata.players[gamedata.numplayers].id == id)
			break;
	}

	if (i==gamedata.numplayers)
		return false;

	strcpy(gamedata.players[i].pname, gamedata.players[gamedata.numplayers].pname);
	strcpy(gamedata.players[i].pteam, gamedata.players[gamedata.numplayers].pteam);
	gamedata.players[i].id = gamedata.players[gamedata.numplayers].id;
	gamedata.numplayers--;

	goa_send_statechanged();

	return true;
}

//========================================================================
//========================================================================
extern bool UpdateGameSpyGameList(void);
bool GameSpyOld::ProcessGameSpy(void)
{
	if (bGameSpy)
	{
		goa_process_queries();
	}

	return true;
}

#endif