// leave this line at the top for all g_xxxx.cpp files...
#include "g_headers.h"


#include "G_Local.h"

typedef map		< string, int >	timer_m;

timer_m	g_timers[ MAX_GENTITIES ];

/*
-------------------------
TIMER_Clear
-------------------------
*/

void TIMER_Clear( void )
{
	for ( int i = 0; i < MAX_GENTITIES; i++ )
	{
		g_timers[i].clear();
	}
}

/*
-------------------------
TIMER_Clear
-------------------------
*/

void TIMER_Clear( gentity_t *ent )
{
	// rudimentary safety checks, might be other things to check?
	if ( ent && ent->s.number > 0 && ent->s.number < MAX_GENTITIES )
	{
		g_timers[ent->s.number].clear();
	}
}


/*
-------------------------
TIMER_Save
-------------------------
*/

void TIMER_Save( void )
{
	int			j;
	gentity_t	*ent;

	for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ )
	{
		int numTimers = g_timers[ent->s.number].size();
		int	i;

		//Write out the timer information
		gi.AppendToSaveGame('TIME', (void *)&numTimers, sizeof(numTimers));
		
		timer_m::iterator	ti;

		for ( i = 0, ti = g_timers[ j ].begin(); i < numTimers; i++, ti++ )
		{
			const char *id = ((*ti).first).c_str();
			int			length = strlen( id );

			//Write out the string size and data
			gi.AppendToSaveGame('TSLN', (void *) &length, sizeof(length) );
			gi.AppendToSaveGame('TSNM', (void *) id, length );

			//Write out the timer data
			gi.AppendToSaveGame('TDTA', (void *) &(*ti).second, sizeof( (*ti).second ) );
		}
	}
}

/*
-------------------------
TIMER_Load
-------------------------
*/

void TIMER_Load( void )
{
	int j;
	gentity_t	*ent;

	for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ )
	{
		int numTimers;

		gi.ReadFromSaveGame( 'TIME', (void *)&numTimers, sizeof(numTimers) );

		//Make sure there's something to read
		if ( numTimers == 0 )
			continue;
		
		//Read back all entries
		for ( int i = 0; i < numTimers; i++ )
		{
			int		length, time;
			char	tempBuffer[1024];	//FIXME: Blech!

			gi.ReadFromSaveGame( 'TSLN', (void *) &length, sizeof( length ) );

			//Validity check, though this will never happen (unless of course you pass in gibberish)
			if ( length >= 1024 )
			{
				assert(0);
				continue;
			}

			//Read the id and time
			gi.ReadFromSaveGame( 'TSNM', (char *) tempBuffer, length );
			gi.ReadFromSaveGame( 'TDTA', (void *) &time, sizeof( time ) );

			//Restore it
			g_timers[ j ][(const char *) tempBuffer ] = time;
		}
	}
}

/*
-------------------------
TIMER_Set
-------------------------
*/

void TIMER_Set( gentity_t *ent, const char *identifier, int duration )
{
	g_timers[ent->s.number][identifier] = level.time + duration;
}

/*
-------------------------
TIMER_Get
-------------------------
*/

int	TIMER_Get( gentity_t *ent, const char *identifier )
{
	timer_m::iterator	ti;

	ti = g_timers[ent->s.number].find( identifier );

	if ( ti == g_timers[ent->s.number].end() )
	{
		//assert(0);
		return -1;
	}

	return (*ti).second;
}

/*
-------------------------
TIMER_Done
-------------------------
*/

qboolean TIMER_Done( gentity_t *ent, const char *identifier )
{
	timer_m::iterator	ti;

	ti = g_timers[ent->s.number].find( identifier );

	if ( ti == g_timers[ent->s.number].end() )
		return true;

	return ( (*ti).second < level.time );
}

/*
-------------------------
TIMER_Done2

Returns false if timer has been 
started but is not done...or if 
timer was never started
-------------------------
*/

qboolean TIMER_Done2( gentity_t *ent, const char *identifier, qboolean remove )
{
	timer_m::iterator	ti;

	ti = g_timers[ent->s.number].find( identifier );

	if ( ti == g_timers[ent->s.number].end() )
	{
		return qfalse;
	}

	qboolean res =((*ti).second < level.time );

	if ( res && remove )
	{
		// Timer is done and it was requested that it should be removed.
		g_timers[ent->s.number].erase( ti );
	}

	return res;
}

/*
-------------------------
TIMER_Exists
-------------------------
*/
qboolean TIMER_Exists( gentity_t *ent, const char *identifier )
{
	timer_m::iterator	ti;

	ti = g_timers[ent->s.number].find( identifier );

	if ( ti == g_timers[ent->s.number].end( ))
	{
		return qfalse;
	}

	return qtrue;
}

/*
-------------------------
TIMER_Remove
Utility to get rid of any timer
-------------------------
*/
void TIMER_Remove( gentity_t *ent, const char *identifier )
{
	timer_m::iterator	ti;

	ti = g_timers[ent->s.number].find( identifier );

	if ( ti != g_timers[ent->s.number].end() )
	{
		g_timers[ent->s.number].erase( ti );
	}
}

/*
-------------------------
TIMER_Start
-------------------------
*/

qboolean TIMER_Start( gentity_t *self, const char *identifier, int duration )
{
	if ( TIMER_Done( self, identifier ) )
	{
		TIMER_Set( self, identifier, duration );
		return qtrue;
	}
	return qfalse;
}
