//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ====
//
//
//=============================================================================

#include "cbase.h"
//#include "entityinput.h"
//#include "entityoutput.h"
//#include "eventqueue.h"
#include "hl2wars/logic_victoryconditions.h"
#include "hl2wars/rts_globalresource.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

LINK_ENTITY_TO_CLASS(logic_rts_victoryconditions, CLogicVictoryConditions);

BEGIN_DATADESC( CLogicVictoryConditions )
	DEFINE_KEYFIELD(m_bDisabled, FIELD_BOOLEAN, "StartDisabled"),

	DEFINE_KEYFIELD(m_VictoryCondition, FIELD_INTEGER, "victorycondition" ),
	DEFINE_KEYFIELD(m_FailureCondition, FIELD_INTEGER, "failurecondition" ),
 
	// fields
	DEFINE_ARRAY( m_bVictory, FIELD_BOOLEAN, MAX_TEAMS_ID_RTS ),
	DEFINE_ARRAY( m_bFailure, FIELD_BOOLEAN, MAX_TEAMS_ID_RTS ),

	// Inputs
	DEFINE_INPUTFUNC(FIELD_VOID, "Enable", InputEnable),
	DEFINE_INPUTFUNC(FIELD_VOID, "Disable", InputDisable),
	DEFINE_INPUTFUNC(FIELD_VOID, "Toggle", InputToggle),

	DEFINE_INPUTFUNC(FIELD_INTEGER, "ChangeVictoryCond", InputChangeVictoryCond),
	DEFINE_INPUTFUNC(FIELD_INTEGER, "ChangeFailureCond", InputChangeFailureCond),

	// Outputs
	DEFINE_OUTPUT(m_OnSpawn, "OnSpawn"),

	DEFINE_OUTPUT(m_OnVictory3, "OnVictory_t3"),
	DEFINE_OUTPUT(m_OnVictory4, "OnVictory_t4"),
	DEFINE_OUTPUT(m_OnVictory5, "OnVictory_t5"),
	DEFINE_OUTPUT(m_OnVictory6, "OnVictory_t6"),
	DEFINE_OUTPUT(m_OnVictory7, "OnVictory_t7"),
	DEFINE_OUTPUT(m_OnVictory8, "OnVictory_t8"),
	DEFINE_OUTPUT(m_OnVictory9, "OnVictory_t9"),
	DEFINE_OUTPUT(m_OnVictory10, "OnVictory_t10"),

	DEFINE_OUTPUT(m_OnFailure3, "OnFailure_t3"),
	DEFINE_OUTPUT(m_OnFailure4, "OnFailure_t4"),
	DEFINE_OUTPUT(m_OnFailure5, "OnFailure_t5"),
	DEFINE_OUTPUT(m_OnFailure6, "OnFailure_t6"),
	DEFINE_OUTPUT(m_OnFailure7, "OnFailure_t7"),
	DEFINE_OUTPUT(m_OnFailure8, "OnFailure_t8"),
	DEFINE_OUTPUT(m_OnFailure9, "OnFailure_t9"),
	DEFINE_OUTPUT(m_OnFailure10, "OnFailure_t10"),

END_DATADESC()

//-----------------------------------------------------------------------------
// Purpose: Constructor.
//-----------------------------------------------------------------------------
CLogicVictoryConditions::CLogicVictoryConditions(void)
{
	for( int i = 0; i < MAX_TEAMS_ID_RTS; i++ )
	{
		m_bVictory[i] = false;
		m_bFailure[i] = false;	
	}
}

void CLogicVictoryConditions::Activate()
{
	BaseClass::Activate();
	
	if( !m_bDisabled )
	{
		// Start thinking
		//SetThink( &CLogicVictoryConditions::OnThink );
		SetNextThink( gpGlobals->curtime + 0.5f );
	}
}

//------------------------------------------------------------------------------
// Purpose: Turns on the relay, allowing it to fire outputs.
//------------------------------------------------------------------------------
void CLogicVictoryConditions::InputEnable( inputdata_t &inputdata )
{
	m_bDisabled = false;

	//SetThink( &CLogicVictoryConditions::OnThink );
	SetNextThink( gpGlobals->curtime + 0.5f );
}

//------------------------------------------------------------------------------
// Purpose: Turns off the relay, preventing it from firing outputs.
//------------------------------------------------------------------------------
void CLogicVictoryConditions::InputDisable( inputdata_t &inputdata )
{ 
	m_bDisabled = true;

	//SetThink( NULL );
}


//------------------------------------------------------------------------------
// Purpose: Toggles the enabled/disabled state of the relay.
//------------------------------------------------------------------------------
void CLogicVictoryConditions::InputToggle( inputdata_t &inputdata )
{ 
	m_bDisabled = !m_bDisabled;

	if( m_bDisabled )
		InputDisable( inputdata );
	else
        InputEnable( inputdata );
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::InputChangeVictoryCond( inputdata_t &inputdata ) 
{
	if( m_bDisabled )
		return;

	// make sure it's an int, if it can't be converted just throw it away
	if ( !inputdata.value.Convert(FIELD_INTEGER) )
		return;

	m_VictoryCondition = inputdata.value.Int(); 
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::InputChangeFailureCond( inputdata_t &inputdata ) 
{
	if( m_bDisabled )
		return;

	// make sure it's an int, if it can't be converted just throw it away
	if ( !inputdata.value.Convert(FIELD_INTEGER) )
		return;

	m_FailureCondition = inputdata.value.Int(); 
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::Think( void )
{
	SetNextThink( gpGlobals->curtime + 0.5f );

	// check failure conditions first
	switch( m_FailureCondition )
	{
		case FCOND_CUSTOM:
			break;	// do nothing, it's custom ;)
		case FCOND_UNITS_DEAD:
			CheckUnitCount();
			break;
		case FCOND_NO_CAPTUREPOINTS:
			CheckCapturePoints();
			break;
		case FCOND_BASE_DEAD:
			CheckBaseCount();
			break;
		case FCOND_UNITS_AND_BASE_DEAD:
			CheckBaseAndUnitCount();
			break;
		default:
			break;
	}

	// now check victory conditions
	switch( m_VictoryCondition )
	{
		case VCOND_CUSTOM:
			break;	// do nothing, it's custom ;)
		case VCOND_OBJS_COMPLETED:
			break;
		case VCON_ALLCP_CAPTURED:
			CheckCapturePointsWin();
			break;
		default:
			break;
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::CheckUnitCount( void )
{
	for( int i = 3; i < MAX_TEAMS_ID_RTS + DEFAULT_TEAMS; i++ )
	{
		if( m_bFailure[i - DEFAULT_TEAMS] )
			continue;

		if( g_pRTSResource->GetSize( i ) == 0 )
			Failure(i);
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::CheckCapturePoints( void )
{
	for( int i = 3; i < MAX_TEAMS_ID_RTS + DEFAULT_TEAMS; i++ )
	{
		if( m_bFailure[i - DEFAULT_TEAMS] )
			continue;
		
		if( g_pRTSResource->m_pCapturePointList->GetCount( i ) == 0 )
			Failure(i);
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::CheckCapturePointsWin( void )
{
	for( int i = 3; i < MAX_TEAMS_ID_RTS + DEFAULT_TEAMS; i++ )
	{
		if( m_bVictory[i - DEFAULT_TEAMS] )
			continue;
		
		if( g_pRTSResource->m_pCapturePointList->GetCount( i ) == g_pRTSResource->m_pCapturePointList->GetTotal() )
			Victory(i);
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::CheckBaseCount( void )
{
	for( int i = 3; i < MAX_TEAMS_ID_RTS + DEFAULT_TEAMS; i++ )
	{
		if( m_bFailure[i - DEFAULT_TEAMS] )
			continue;

		if( g_pRTSResource->GetModelBuildingCount(i) == 0 )
			Failure(i);
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::CheckBaseAndUnitCount( void )
{
	for( int i = 3; i < MAX_TEAMS_ID_RTS + DEFAULT_TEAMS; i++ )
	{
		if( m_bFailure[i - DEFAULT_TEAMS] )
			continue;

		if( g_pRTSResource->GetModelBuildingCount(i) == 0 && g_pRTSResource->GetSize( i ) == 0 )
			Failure(i);
	}
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::Victory( int teamid )
{
	//m_OnVictory[teamid].FireOutput( this, this );
	switch( teamid )
	{
	case 3:
		m_OnVictory3.FireOutput( this, this );
		break;
	case 4:
		m_OnVictory4.FireOutput( this, this );
		break;
	case 5:
		m_OnVictory5.FireOutput( this, this );
		break;
	case 6:
		m_OnVictory6.FireOutput( this, this );
		break;
	case 7:
		m_OnVictory7.FireOutput( this, this );
		break;
	case 8:
		m_OnVictory8.FireOutput( this, this );
		break;
	case 9:
		m_OnVictory9.FireOutput( this, this );
		break;
	case 10:
		m_OnVictory10.FireOutput( this, this );
		break;
	default:
		break;
	}
	m_bVictory[teamid] = true;
}

//------------------------------------------------------------------------------
// Purpose:
//------------------------------------------------------------------------------
void CLogicVictoryConditions::Failure( int teamid )
{
	//m_OnFailure[teamid].FireOutput( this, this );
	switch( teamid )
	{
	case 3:
		m_OnFailure3.FireOutput( this, this );
		break;
	case 4:
		m_OnFailure4.FireOutput( this, this );
		break;
	case 5:
		m_OnFailure5.FireOutput( this, this );
		break;
	case 6:
		m_OnFailure6.FireOutput( this, this );
		break;
	case 7:
		m_OnFailure7.FireOutput( this, this );
		break;
	case 8:
		m_OnFailure8.FireOutput( this, this );
		break;
	case 9:
		m_OnFailure9.FireOutput( this, this );
		break;
	case 10:
		m_OnFailure10.FireOutput( this, this );
		break;
	default:
		break;
	}
	m_bFailure[teamid] = true;
}