/*
Copyright (C) 2002-2003 Victor Luchits

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 "cg_local.h"

//==================
//CG_SC_Print
//==================
void CG_SC_Print( void )
{
	CG_Printf( "%s", trap_Cmd_Argv(1) );
}

//==================
//CG_SC_Print
//==================
void CG_SC_ChatPrint( void )
{
	CG_Printf( "%s", trap_Cmd_Argv(1) );
	trap_S_StartSound( NULL, cgs.playerNum+1, 0, CG_MediaSfx( cgs.media.sfxChat ), 1.0f, ATTN_NONE, 0.0f );
}

//==================
//CG_SC_CenterPrint
//==================
void CG_SC_CenterPrint( void ) {
	SCR_CenterPrint( trap_Cmd_Argv(1) );
}

extern cvar_t			*cg_showObituaries;

//==================
//CG_SC_Obituary
//==================
void CG_SC_Obituary( void )
{
	char message[128];
	char message2[128];
	cg_clientInfo_t *victim, *attacker;
	int victimNum = atoi( trap_Cmd_Argv(1) );
	int attackerNum = atoi( trap_Cmd_Argv(2) );
	int mod = atoi( trap_Cmd_Argv(3) );
	int victim_gender = GENDER_MALE;

	// wsw : jal : extract gender from their player model info, if any
	if( victimNum >= 0 && victimNum < MAX_EDICTS && cg_entPModels[victimNum].pmodelinfo )
		victim_gender = cg_entPModels[victimNum].pmodelinfo->sex;

	victim = &cgs.clientInfo[victimNum - 1];

	if( attackerNum ) {
		attacker = &cgs.clientInfo[attackerNum - 1];
	} else {
		attacker = NULL;
	}

	// wsw : pb : where are obituaries printed
	if( cg_showObituaries->integer != 0 )
	{
		GS_Obituary( victim, victim_gender, attacker, mod, message, message2 );

		if( attackerNum ) {
			if( victimNum != attackerNum ) { 
				// teamkill
				if( cg_entities[attackerNum].current.team == cg_entities[victimNum].current.team
				&& GS_Gametype_IsTeamBased(cg.frame.playerState.stats[STAT_GAMETYPE]) ) {
					if( cg_showObituaries->integer & 1 )
						CG_Printf( "%s%s%s %s %s%s %s%s%s\n", S_COLOR_RED, "TEAMKILL:", S_COLOR_WHITE, victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2 );
					if( attackerNum == cg.chasedNum+1 && cg_showObituaries->integer & 2 ) {
						SCR_CenterPrintToUpper( va("%s%s%s %s\n", S_COLOR_RED, "YOU TEAMKILLED", S_COLOR_WHITE, victim->name ) );
					}
					else if( cg_showObituaries->integer & 4 ) {
						SCR_CenterPrint( va("%s%s%s %s %s%s %s%s%s\n", S_COLOR_RED, "TEAMKILL:", S_COLOR_WHITE, victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2) );
					}
				// good kill
				} else { 
					if( cg_showObituaries->integer & 1 )
						CG_Printf( "%s %s%s %s%s%s\n", victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2 );
					if( attackerNum == cg.chasedNum+1 && cg_showObituaries->integer & 2 ) {
						SCR_CenterPrintToUpper( va("%s%s %s\n", S_COLOR_WHITE, "YOU KILLED", victim->name) );
					}
					else if( cg_showObituaries->integer & 4 ) {
						SCR_CenterPrint( va("%s %s%s %s%s%s\n", victim->name, S_COLOR_WHITE, message, attacker->name, S_COLOR_WHITE, message2) );
					}
				}
			// suicide
			} else {
				if( cg_showObituaries->integer & 1 )
					CG_Printf( "%s %s%s\n", victim->name, S_COLOR_WHITE, message );
				if( cg_showObituaries->integer & 4 )
					SCR_CenterPrint( va( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ) );
			}
		// world accidents
		} else {
			if( cg_showObituaries->integer & 1 )
				CG_Printf( "%s %s%s\n", victim->name, S_COLOR_WHITE, message );
			if( cg_showObituaries->integer & 4 )
				SCR_CenterPrint( va( "%s %s%s\n", victim->name, S_COLOR_WHITE, message ) );
		}
	}
}


//================
//CG_CS_ConfigString
//================
void CG_CS_ConfigString( void )
{
	int		i = atoi( trap_Cmd_Argv(1) );
	char	*s = trap_Cmd_Argv( 2 );
	char	olds[MAX_QPATH];
	int		len;

	// wsw : jal : warn if configstring overflow
	len = strlen( s );
	if( len >= MAX_QPATH )
		CG_Printf( "%sWARNING:%s Configstring %i overflowed\n", S_COLOR_YELLOW, S_COLOR_WHITE, i );

	if ( i < 0 || i >= MAX_CONFIGSTRINGS ) {
		CG_Error( "configstring > MAX_CONFIGSTRINGS" );
	}

	Q_strncpyz( olds, cgs.configStrings[i], sizeof(olds) );
	Q_strncpyz( cgs.configStrings[i], s, sizeof(cgs.configStrings[i]) );

	// do something apropriate 
	if( i == CS_MAPNAME ) {
		CG_RegisterLevelShot();
	} 
	else if( i == CS_SERVERSETTINGS ) {
		CG_UpdateServerSettings();
	}
	else if( i >= CS_MODELS && i < CS_MODELS+MAX_MODELS ) {
		if( cgs.configStrings[i][0] == '$') {	// indexed pmodel
			cgs.pModelsIndex[i-CS_MODELS] = CG_RegisterPlayerModel( cgs.configStrings[i]+1 );
		} else
			cgs.modelDraw[i-CS_MODELS] = CG_RegisterModel( cgs.configStrings[i] );	// skelmod
	} 
	else if( i >= CS_SOUNDS && i < CS_SOUNDS+MAX_SOUNDS ) {
		if( cgs.configStrings[i][0] != '*' ) {
			cgs.soundPrecache[i-CS_SOUNDS] = trap_S_RegisterSound( cgs.configStrings[i] );
		}
	} 
	else if( i >= CS_IMAGES && i < CS_IMAGES+MAX_IMAGES ) {
		cgs.imagePrecache[i-CS_IMAGES] = trap_R_RegisterPic( cgs.configStrings[i] );
	} 
	else if( i >= CS_SKINFILES && i < CS_SKINFILES+MAX_SKINFILES ) {
		cgs.skinPrecache[i-CS_SKINFILES] = trap_R_RegisterSkinFile( cgs.configStrings[i] );
	} 
	else if( i >= CS_LIGHTS && i < CS_LIGHTS+MAX_LIGHTSTYLES ) {
		CG_SetLightStyle( i - CS_LIGHTS );
	} 
	else if( i >= CS_ITEMS && i < CS_ITEMS+MAX_ITEMS ) {
		CG_ValidateItemDef( i - CS_ITEMS, cgs.configStrings[i] );
	} 
	else if( i >= CS_PLAYERINFOS && i < CS_PLAYERINFOS+MAX_CLIENTS ) {
		CG_LoadClientInfo( &cgs.clientInfo[i-CS_PLAYERINFOS], cgs.configStrings[i], i-CS_PLAYERINFOS );
	}
	else if( i >= CS_GAMECOMMANDS && i < CS_GAMECOMMANDS+MAX_GAMECOMMANDS ) {
		trap_Cmd_AddCommand( cgs.configStrings[i], NULL );
	}
}

//================
//CG_SC_Inventory
//================
void CG_SC_Inventory( void )
{
	int		i, rep;
	char	inv[MAX_TOKEN_CHARS], *s;

	Q_strncpyz( inv, trap_Cmd_Argv( 1 ), sizeof( inv ) );

	cg.inventory[0] = 0;	// item 0 is never used
	for( i = 1, s = inv; (i < MAX_ITEMS) && s && *s; i++ ) {
		cg.inventory[i] = atoi( COM_Parse(&s) );
		if( cg.inventory[i] )
			continue;

		for( rep = atoi( COM_Parse(&s) ); (rep > 0) && (i < MAX_ITEMS); rep-- )
			cg.inventory[i++] = 0;
		i--;
	}
}


//================
//CG_SC_Scoreboard	// wsw : jal : scoreboard templates
//================
void SCR_UpdateScoreboardMessage( char *string );
void CG_SC_Scoreboard( void )
{
	SCR_UpdateScoreboardMessage( trap_Cmd_Argv(1) );
}

//================
//CG_SC_AutoRecord
//================
#define CG_AUTORECORD_DO_DEMOS			1
#define CG_AUTORECORD_DO_SCREENSHOT		2
#define CG_AUTORECORD_NOT_WHILE_SPEC	4
//#define CG_AUTORECORD_DO_STATS			8

void CG_SC_AutoRecord( void )
{
	time_t long_time;
	struct tm *newtime;

	char *s = trap_Cmd_Argv(1);
	static char	name[MAX_QPATH];
	static char	mapname[MAX_QPATH];
	char	*cleanplayername;
	char    *cleanplayername2;

	// filter out autorecord commands when playing a demo
	if( cg.demoPlaying )
		return;

	if( !cg_autoaction->integer )
		return;

	// don't do if spectator and 3rd bit isn't set
	if( cg.frame.playerState.pmove.pm_type == PM_SPECTATOR || cg.chasedNum != cgs.playerNum )
		if( !(cg_autoaction->integer & CG_AUTORECORD_NOT_WHILE_SPEC) && !Q_stricmp(s, "start") )
			return;

	// get date from system
	time( &long_time ); 
	newtime = localtime( &long_time ); 

	// remove color tokens from player names (doh)
	cleanplayername = COM_RemoveColorTokens( cgs.clientInfo[cg.chasedNum].name );
	
	// remove junk chars from player names for files
	cleanplayername2 = COM_RemoveJunkChars ( cleanplayername );

	// lowercase mapname
	Q_strncpyz( mapname, cgs.configStrings[CS_MAPNAME], sizeof(mapname) );
	Q_strlwr( mapname );

	// make file name
	// duel_year-month-day_hour-min_map_player
	Q_snprintfz( name, sizeof(name), "%s_%04d-%02d-%02d_%02d-%02d_%s_%s",
				GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE] ),
				newtime->tm_year + 1900, newtime->tm_mon+1, newtime->tm_mday, 
				newtime->tm_hour, newtime->tm_min,
				mapname,
				cleanplayername2
				);

	if( !Q_stricmp(s, "start") ) {
		//start recording

		cg_autoaction = trap_Cvar_Get( "cg_autoaction", "0", CVAR_ARCHIVE );
		if( cg_autoaction->integer & CG_AUTORECORD_DO_DEMOS )	// auto record of demos
		{
			trap_Cmd_ExecuteText( EXEC_NOW, "stop silent" );
			trap_Cmd_ExecuteText( EXEC_NOW, va("record autorecord/%s/%s silent", 
				GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name) );
		}

	} else if( !Q_stricmp(s, "stop") ) {
		//stop recording

		cg_autoaction = trap_Cvar_Get( "cg_autoaction", "0", CVAR_ARCHIVE );

		if( cg_autoaction->integer & CG_AUTORECORD_DO_DEMOS )	// automatic demos
		{
			trap_Cmd_ExecuteText( EXEC_NOW, "stop silent" );
		} 
		
		if( cg_autoaction->integer & CG_AUTORECORD_DO_SCREENSHOT )	// automatic screenshot
		{
			trap_Cmd_ExecuteText( EXEC_NOW, va("screenshot autorecord/%s/%s silent", 
				GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name) );
		}

		/*
		if( cg_autoaction->integer & CG_AUTORECORD_DO_STATS )	// automatic stats
		{
			//trap_Cmd_ExecuteText( EXEC_NOW, "clear");
			trap_Cmd_ExecuteText( EXEC_NOW, "stats");
			trap_Cmd_ExecuteText( EXEC_NOW, va("condump stats/%s/%s", 
				GS_Gametype_ShortName( cg.frame.playerState.stats[STAT_GAMETYPE]), name)
				);
		} 
		*/

	} else if( !Q_stricmp(s, "cancel") ) {
		// cancel the record
		trap_Cmd_ExecuteText( EXEC_NOW, "stop cancel silent" );
	}
	else if( developer->integer )
		CG_Printf( "CG_SC_AutoRecord: Unknown argument: %s\n", s );
}

//=======================================================

void CG_SC_MatchMessage( void ) {
	Q_strncpyz( cg.matchmessage, trap_Cmd_Argv(1), sizeof(cg.matchmessage) );
}

void CG_CS_UpdateTeamInfo( void ) {
	Q_strncpyz( cg.teaminfo, trap_Cmd_Argv(1), sizeof(cg.teaminfo) );
}

//=======================================================

void CG_SC_Layout( void ) {
	CG_LoadLayout( trap_Cmd_Argv(1) );
}

//=======================================================

typedef struct
{
	char	*name;
	void	(*func) (void);
} svcmd_t;

svcmd_t cg_svcmds[] =
{
	{ "pr", CG_SC_Print },
	{ "ch", CG_SC_ChatPrint },
	{ "cp", CG_SC_CenterPrint },
	{ "obry", CG_SC_Obituary },
	{ "cs", CG_CS_ConfigString },
	{ "inv", CG_SC_Inventory },
	{ "scb", CG_SC_Scoreboard }, // wsw : jal : scoreboard templates
	{ "autr", CG_SC_AutoRecord }, // wsw : jal : autorecord command
	{ "mm", CG_SC_MatchMessage },
	{ "layout", CG_CS_ConfigString },
	{ "ti", CG_CS_UpdateTeamInfo },

	{ NULL }
};

/*
==================
CG_ServerCommand
==================
*/
void CG_ServerCommand (void)
{
	char *s;
	svcmd_t *cmd;

	s = trap_Cmd_Argv ( 0 );
	for (cmd = cg_svcmds; cmd->name; cmd++) {
		if (!strcmp (s, cmd->name) ) {
			cmd->func ();
			return;
		}
	}
}
