//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: 
//
// $NoKeywords: $
//=============================================================================

#include "cbase.h"
#include "hud.h"
#include "hudelement.h"
#include "c_tf_player.h"
#include "iclientmode.h"
#include "ienginevgui.h"
#include <vgui/ILocalize.h>
#include <vgui/ISurface.h>
#include <vgui/IVGui.h>
#include "c_baseobject.h"
#include "tf_gamerules.h"
#include "tf_item_inventory.h"
#include "tf_hud_menu_spy_build.h"

// NVNT haptics for buildings
#include "haptics/haptic_utils.h"

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

#ifdef STAGING_ONLY

using namespace vgui;

// Set to 1 to simulate xbox-style menu interaction
extern ConVar tf_build_menu_controller_mode;

const SpyConstructBuilding_t g_kSpyBuildings[ NUM_SPY_BUILDINGS ] =
{
	// Sap Trap
	SpyConstructBuilding_t( true,
							OBJ_SPY_TRAP,
							MODE_SPY_TRAP_RADIUS_STEALTH,
							"spy_trap_active.res",
							"spy_trap_already_built.res",
							"spy_trap_cant_afford.res",
							"spy_trap_unavailable.res",
							"spy_trap_active.res",
							"spy_trap_inactive.res",
							"spy_trap_inactive.res" ), 

	// Reprogrammer
	SpyConstructBuilding_t( true,
							OBJ_SPY_TRAP,
							MODE_SPY_TRAP_REPROGRAM,
							"spy_trap_reprog_active.res",
							"spy_trap_reprog_already_built.res",
							"spy_trap_reprog_cant_afford.res",
							"spy_trap_reprog_unavailable.res",
							"spy_trap_reprog_active.res",
							"spy_trap_reprog_inactive.res",
							"spy_trap_reprog_inactive.res" ),

	// Pulse Magnet
	SpyConstructBuilding_t( true,
							OBJ_SPY_TRAP,
							MODE_SPY_TRAP_MAGNET,
							"spy_trap_magnet_active.res",
							"spy_trap_magnet_already_built.res",
							"spy_trap_magnet_cant_afford.res",
							"spy_trap_magnet_unavailable.res",
							"spy_trap_magnet_active.res",
							"spy_trap_magnet_inactive.res",
							"spy_trap_magnet_inactive.res" ),

// 	// Repulsor
// 	SpyConstructBuilding_t( true,
// 							 OBJ_SPY_TRAP,
// 							 MODE_SPY_TRAP_REPULSOR,
// 							 "tele_exit_active.res",
// 							 "tele_exit_already_built.res",
// 							 "tele_exit_cant_afford.res",
// 							 "tele_exit_unavailable.res",
// 							 "tele_exit_active.res",
// 							 "tele_exit_inactive.res",
// 							 "tele_exit_inactive.res" )
};


static int trapSlots[NUM_SPY_BUILDINGS] =
{
	0x01,
 	0x02
// 	0x04,
};

const SpyConstructBuildingReplacement_t s_alternateSpyBuildings[] =
{
	// Temp - modify this
	SpyConstructBuildingReplacement_t(
	OBJ_CATAPULT,
	0,
	"spy_trap_active.res",
	"spy_trap_already_built.res",
	"spy_trap_cant_afford.res",
	"spy_trap_unavailable.res",
	"spy_trap_active.res",
	"spy_trap_inactive.res",
	"spy_trap_inactive.res",
	trapSlots[0],
	trapSlots[1]
	),
	// Add more objects here
};


//======================================
DECLARE_HUDELEMENT_DEPTH( CHudMenuSpyBuild, 40 );

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
CHudMenuSpyBuild::CHudMenuSpyBuild( const char *pElementName ) 
	: CHudBaseBuildMenu( pElementName, "HudMenuSpyBuild" )
{
	Panel *pParent = g_pClientMode->GetViewport();
	SetParent( pParent );

	SetHiddenBits( HIDEHUD_MISCSTATUS );

	for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
	{
		char buf[32];

		Q_snprintf( buf, sizeof(buf), "active_item_%d", i+1 );
		m_pAvailableObjects[i] = new EditablePanel( this, buf );

		Q_snprintf( buf, sizeof(buf), "already_built_item_%d", i+1 );
		m_pAlreadyBuiltObjects[i] = new EditablePanel( this, buf );

		Q_snprintf( buf, sizeof(buf), "cant_afford_item_%d", i+1 );
		m_pCantAffordObjects[i] = new EditablePanel( this, buf );

		Q_snprintf( buf, sizeof(buf), "unavailable_item_%d", i+1 );
		m_pUnavailableObjects[i] = new EditablePanel( this, buf );
	}

	vgui::ivgui()->AddTickSignal( GetVPanel() );

	m_pActiveSelection = NULL;
	m_iSelectedItem = -1;
	m_pBuildLabelBright = NULL;
	m_pBuildLabelDim = NULL;
	m_pDestroyLabelBright = NULL;
	m_pDestroyLabelDim = NULL;
	m_bInConsoleMode = false;
	m_iCurrentBuildMenuLayout = SPY_BUILDMENU_DEFAULT;

	RegisterForRenderGroup( "mid" );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::ApplySchemeSettings( IScheme *pScheme )
{
	// load control settings...
	bool b360Style = ( IsConsole() || tf_build_menu_controller_mode.GetBool() );
	if ( b360Style )
	{
		// This entire block is unused and ancient.  Will need to support a controller
		// once we deem spy traps as shippable, but for now they're a prototype.

// 		LoadControlSettings( "resource/UI/build_menu_360/HudMenuSpyBuild.res" );
// 
// 		// Load the already built images, destroyable
// 		m_pAlreadyBuiltObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_already_built.res" );
// 		m_pAlreadyBuiltObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_already_built.res" );
// 		m_pAlreadyBuiltObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_already_built.res" );
// 		m_pAlreadyBuiltObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_already_built.res" );
// 
// 		m_pAvailableObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_active.res" );
// 		m_pAvailableObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_active.res" );
// 		m_pAvailableObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_active.res" );
// 		m_pAvailableObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_active.res" );
// 
// 		m_pCantAffordObjects[0]->LoadControlSettings( "resource/UI/build_menu_360/sentry_cant_afford.res" );
// 		m_pCantAffordObjects[1]->LoadControlSettings( "resource/UI/build_menu_360/dispenser_cant_afford.res" );
// 		m_pCantAffordObjects[2]->LoadControlSettings( "resource/UI/build_menu_360/tele_entrance_cant_afford.res" );
// 		m_pCantAffordObjects[3]->LoadControlSettings( "resource/UI/build_menu_360/tele_exit_cant_afford.res" );
// 
// 		m_pUnavailableObjects[0]->LoadControlSettings( "resource/UI/build_menu/sentry_unavailable.res" );
// 		m_pUnavailableObjects[1]->LoadControlSettings( "resource/UI/build_menu/dispenser_unavailable.res" );
// 		m_pUnavailableObjects[2]->LoadControlSettings( "resource/UI/build_menu/tele_entrance_unavailable.res" );
// 		m_pUnavailableObjects[3]->LoadControlSettings( "resource/UI/build_menu/tele_exit_unavailable.res" );
// 
// 		m_pActiveSelection = dynamic_cast< CIconPanel * >( FindChildByName( "active_selection_bg" ) );
// 		m_pBuildLabelBright = dynamic_cast< CExLabel * >( FindChildByName( "BuildHintLabel_Bright" ) );
// 		m_pBuildLabelDim = dynamic_cast< CExLabel * >( FindChildByName( "BuildHintLabel_Dim" ) );
// 		m_pDestroyLabelBright = dynamic_cast< CExLabel * >( FindChildByName( "DestroyHintLabel_Bright" ) );
// 		m_pDestroyLabelDim = dynamic_cast< CExLabel * >( FindChildByName( "DestroyHintLabel_Dim" ) );

		// Reposition the activeselection to the default position
		m_iSelectedItem = -1;	// force reposition
		SetSelectedItem( 1 );
	}
	else
	{
		const char *pszCustomDir = NULL;
		switch( m_iCurrentBuildMenuLayout )
		{
		default:
		case SPY_BUILDMENU_DEFAULT:
			pszCustomDir = "resource/UI/build_menu";
			break;
		}

		LoadControlSettings( VarArgs("%s/HudMenuSpyBuild.res",pszCustomDir) );

		// Load the already built images, not destroyable
		for ( int i = 0; i < NUM_SPY_BUILDINGS; ++i )
		{
			m_pAvailableObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructAvailableObjectRes ) );
			m_pAlreadyBuiltObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructAlreadyBuiltObjectRes ) );
			m_pCantAffordObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructCantAffordObjectRes ) );
			m_pUnavailableObjects[i]->LoadControlSettings( VarArgs( "%s/%s", pszCustomDir, m_Buildings[i].m_pszConstructUnavailableObjectRes ) );
		}

		m_pActiveSelection = NULL;
		m_pBuildLabelBright = NULL;
		m_pBuildLabelDim = NULL;
		m_pDestroyLabelBright = NULL;
		m_pDestroyLabelDim = NULL;
	}

	// Set the cost label
	for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
	{
		int iBuilding, iMode;
		GetBuildingIDAndModeFromSlot( i+1, iBuilding, iMode, m_Buildings );
		int iCost = GetObjectInfo( iBuilding )->m_Cost;

		m_pAvailableObjects[i]->SetDialogVariable( "metal", iCost );
		m_pAlreadyBuiltObjects[i]->SetDialogVariable( "metal", iCost );
		m_pCantAffordObjects[i]->SetDialogVariable( "metal", iCost );
		m_pUnavailableObjects[i]->SetDialogVariable( "metal", iCost );
	}

	BaseClass::ApplySchemeSettings( pScheme );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool CHudMenuSpyBuild::ShouldDraw( void )
{
	if ( !TFGameRules() || !TFGameRules()->GameModeUsesUpgrades() )
		return false;

	CTFPlayer *pPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pPlayer )
		return false;

	if ( !pPlayer->m_Shared.CanBuildSpyTraps() )
		return false;

	return BaseClass::ShouldDraw();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::GetBuildingIDAndModeFromSlot( int iSlot, int &iBuilding, int &iMode, const SpyConstructBuilding_t (&buildings)[ NUM_SPY_BUILDINGS ] )
{
	iBuilding = OBJ_LAST;
	iMode = 0;
	int index = iSlot - 1;
	if ( index >= 0 && index < NUM_SPY_BUILDINGS )
	{
		iBuilding = buildings[index].m_iObjectType;
		iMode = buildings[index].m_iMode;
	}
	else
	{
		Assert( !"What slot are we asking for and why?" );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Keyboard input hook. Return 0 if handled
//-----------------------------------------------------------------------------
int	CHudMenuSpyBuild::HudElementKeyInput( int down, ButtonCode_t keynum, const char *pszCurrentBinding )
{
	if ( !ShouldDraw() )
		return 1;

	if ( !down )
		return 1;

	bool bController = ( IsConsole() || ( keynum >= JOYSTICK_FIRST ) );
	if ( bController )
	{
		int iNewSelection = m_iSelectedItem;

		switch( keynum )
		{
		case KEY_XBUTTON_UP:
		case STEAMCONTROLLER_DPAD_UP:
			// jump to last
			iNewSelection = NUM_SPY_BUILDINGS;
			break;

		case KEY_XBUTTON_DOWN:
		case STEAMCONTROLLER_DPAD_DOWN:
			// jump to first
			iNewSelection = 1;
			break;

		case KEY_XBUTTON_RIGHT:
		case STEAMCONTROLLER_DPAD_RIGHT:
			// move selection to the right
			iNewSelection++;
			if ( iNewSelection > NUM_SPY_BUILDINGS )
				iNewSelection = 1;
			break;

		case KEY_XBUTTON_LEFT:
		case STEAMCONTROLLER_DPAD_LEFT:
			// move selection to the left
			iNewSelection--;
			if ( iNewSelection < 1 )
				iNewSelection = NUM_SPY_BUILDINGS;
			break;

		case KEY_XBUTTON_A:
		case KEY_XBUTTON_RTRIGGER:
		case STEAMCONTROLLER_A:
			// build selected item
			SendBuildMessage( m_iSelectedItem );
			return 0;

		case KEY_XBUTTON_Y:
		case KEY_XBUTTON_LTRIGGER:
		case STEAMCONTROLLER_Y:
			{
				// destroy selected item
				bool bSuccess = SendDestroyMessage( m_iSelectedItem );

				if ( bSuccess )
				{
					engine->ExecuteClientCmd( "lastinv" );
				}
			}
			return 0;

		case KEY_XBUTTON_B:
		case STEAMCONTROLLER_B:
			// cancel, close the menu
			engine->ExecuteClientCmd( "lastinv" );
			return 0;

		default:
			return 1;	// key not handled
		}

		SetSelectedItem( iNewSelection );

		return 0;
	}
	else
	{
		int iSlot = 0;

		// convert slot1, slot2 etc to 1,2,3,4
		if( pszCurrentBinding && ( !Q_strncmp( pszCurrentBinding, "slot", NUM_SPY_BUILDINGS ) && Q_strlen(pszCurrentBinding) > NUM_SPY_BUILDINGS ) )
		{
			const char *pszNum = pszCurrentBinding + Q_strlen( "slot" );
			iSlot = atoi(pszNum);

			// slot10 cancels
			if ( iSlot == 10 )
			{
				engine->ExecuteClientCmd( "lastinv" );
				return 0;
			}

			// allow slot1 - slot4 
			if ( iSlot < 1 || iSlot > NUM_SPY_BUILDINGS )
				return 1;
		}
		else
		{
			switch( keynum )
			{
			case KEY_1:
				iSlot = 1;
				break;
			case KEY_2:
				iSlot = 2;
				break;
			case KEY_3:
				iSlot = 3;
				break;
			case KEY_4:
				iSlot = 4;
				break;

			case KEY_5:
			case KEY_6:
			case KEY_7:
			case KEY_8:
			case KEY_9:
				// Eat these keys
				return 0;

			case KEY_0:
			case KEY_XBUTTON_B:
			case STEAMCONTROLLER_B:
				// cancel, close the menu
				engine->ExecuteClientCmd( "lastinv" );
				return 0;

			default:
				return 1;	// key not handled
			}
		}		

		if ( iSlot > 0 )
		{
			SendBuildMessage( iSlot );
			return 0;
		}
	}

	return 1;	// key not handled
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::SendBuildMessage( int iSlot )
{
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();

	if ( !pLocalPlayer )
		return;

	int iBuilding, iMode;
	GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );

	if ( CanBuild( iSlot ) == false )
	{
		return;
	}

	C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );
	int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );

	if ( !pObj && pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 ) >= iCost )
	{
		char szCmd[128];
		Q_snprintf( szCmd, sizeof(szCmd), "build %d %d", iBuilding, iMode );
		engine->ClientCmd( szCmd );
		// NVNT send the build command
		if ( haptics )
			haptics->ProcessHapticEvent(2, "Game", szCmd);
	}
	else
	{
		pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
	}
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CHudMenuSpyBuild::SendDestroyMessage( int iSlot )
{
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();

	if ( !pLocalPlayer )
		return false;

	bool bSuccess = false;

	int iBuilding, iMode;
	GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );

	C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );

	if ( pObj != NULL )
	{
		char szCmd[128];
		Q_snprintf( szCmd, sizeof(szCmd), "destroy %d %d", iBuilding, iMode );
		engine->ClientCmd( szCmd );
		// NVNT send the destroy command
		if ( haptics )
			haptics->ProcessHapticEvent(2, "Game", szCmd);
		bSuccess = true; 
	}
	else
	{
		pLocalPlayer->EmitSound( "Player.DenyWeaponSelection" );
	}

	return bSuccess;
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::OnTick( void )
{
	if ( !IsVisible() )
		return;

	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();

	if ( !pLocalPlayer )
		return;

	int iAmmo = pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 );

	for ( int i = 0;i < NUM_SPY_BUILDINGS; i++ )
	{
		int iRemappedObjectID, iMode;
		GetBuildingIDAndModeFromSlot( i + 1, iRemappedObjectID, iMode, m_Buildings );

		// update this slot
		C_BaseObject *pObj = NULL;

		if ( pLocalPlayer )
		{
			pObj = pLocalPlayer->GetObjectOfType( iRemappedObjectID, iMode );
		}

		m_pAvailableObjects[i]->SetVisible( false );
		m_pAlreadyBuiltObjects[i]->SetVisible( false );
		m_pCantAffordObjects[i]->SetVisible( false );
		m_pUnavailableObjects[i]->SetVisible( false );

		if ( !m_Buildings[i].m_bEnabled )
		{
			continue;
		}

		int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iRemappedObjectID );
		bool bAvailable = CanBuild( i + 1 );

		// If the building is already built, and we don't have an ability to build more than one (sentry)
		if ( pObj != NULL && !pObj->IsPlacing() && !( pLocalPlayer->CanBuild( iRemappedObjectID, iMode ) == CB_CAN_BUILD ) )
		{
			m_pAlreadyBuiltObjects[i]->SetVisible( true );
		}
		// unavailable
		else if ( bAvailable == false )
		{
			m_pUnavailableObjects[i]->SetVisible( true );
		}
		// See if we can afford it
		else if ( iAmmo < iCost )
		{
			m_pCantAffordObjects[i]->SetVisible( true );
		}
		else
		{
			// we can buy it
			m_pAvailableObjects[i]->SetVisible( true );
		}
	}
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::SetVisible( bool state )
{
	if ( state == true )
	{
		InitBuildings();

		// close the weapon selection menu
		engine->ClientCmd( "cancelselect" );

		bool bConsoleMode = ( IsConsole() || tf_build_menu_controller_mode.GetBool() );

		if ( bConsoleMode != m_bInConsoleMode )
		{
			InvalidateLayout( true, true );
			m_bInConsoleMode = bConsoleMode;
		}
		else
		{
			// See if our layout needs to change, due to equipped items
			int iDesired = CalcCustomBuildMenuLayout();
			if ( iDesired != m_iCurrentBuildMenuLayout )
			{
				m_iCurrentBuildMenuLayout = (spybuildmenulayouts_t)iDesired;
				InvalidateLayout( true, true );
			}
		}

		// set the %lastinv% dialog var to our binding
		const char *key = engine->Key_LookupBinding( "lastinv" );
		if ( !key )
		{
			key = "< not bound >";
		}

		SetDialogVariable( "lastinv", key );

		// Set selection to the first available building that we can build

		C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
		if ( !pLocalPlayer )
			return;

		int iDefaultSlot = 1;

		// Find the first slot that represents a building that we haven't built
		int iSlot;
		for ( iSlot = 1; iSlot <= NUM_SPY_BUILDINGS; iSlot++ )
		{
			int iBuilding, iMode;
			GetBuildingIDAndModeFromSlot( iSlot, iBuilding, iMode, m_Buildings );
			C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding, iMode );

			if ( pObj == NULL )
			{
				iDefaultSlot = iSlot;
				break;
			}
		}

		m_iSelectedItem = -1;	//force redo
		SetSelectedItem( iDefaultSlot );

		HideLowerPriorityHudElementsInGroup( "mid" );

		for ( int i = 0; i < NUM_SPY_BUILDINGS; i++ )
		{
			int iBuilding, iMode;
			GetBuildingIDAndModeFromSlot( i + 1, iBuilding, iMode, m_Buildings );
			int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );
			m_pAvailableObjects[i]->SetDialogVariable( "metal", iCost );
			m_pAlreadyBuiltObjects[i]->SetDialogVariable( "metal", iCost );
			m_pCantAffordObjects[i]->SetDialogVariable( "metal", iCost );
		}
	}
	else
	{
		UnhideLowerPriorityHudElementsInGroup( "mid" );
	}

	BaseClass::SetVisible( state );
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::SetSelectedItem( int iSlot )
{
	if ( m_iSelectedItem != iSlot )
	{
		m_iSelectedItem = iSlot;

		// move the selection item to the new position
		if ( m_pActiveSelection )
		{
			// move the selection background
			int x, y;
			m_pAlreadyBuiltObjects[m_iSelectedItem-1]->GetPos( x, y );

			x -= XRES(NUM_SPY_BUILDINGS);
			y -= XRES(NUM_SPY_BUILDINGS);

			m_pActiveSelection->SetPos( x, y );

			UpdateHintLabels();			
		}
	}
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::UpdateHintLabels( void )
{
	// hilight the action we can perform ( build or destroy or neither )
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();

	if ( pLocalPlayer )
	{
		int iBuilding, iMode;
		GetBuildingIDAndModeFromSlot( m_iSelectedItem, iBuilding, iMode, m_Buildings );
		C_BaseObject *pObj = pLocalPlayer->GetObjectOfType( iBuilding );

		bool bDestroyLabelBright = false;
		bool bBuildLabelBright = false;

		int iCost = pLocalPlayer->m_Shared.CalculateObjectCost( pLocalPlayer, iBuilding );

		if ( pObj )
		{
			// hilight destroy, we have a building
			bDestroyLabelBright = true;
		}
		else if ( pLocalPlayer->GetAmmoCount( TF_AMMO_GRENADES1 ) >= iCost )	// I can afford it
		{
			// hilight build, we can build this
			bBuildLabelBright = true;
		}
		else
		{
			// dim both, do nothing
		}

		if ( m_pDestroyLabelBright && m_pDestroyLabelDim && m_pBuildLabelBright && m_pBuildLabelDim )
		{
			m_pDestroyLabelBright->SetVisible( bDestroyLabelBright );
			m_pDestroyLabelDim->SetVisible( !bDestroyLabelBright );
			m_pBuildLabelBright->SetVisible( bBuildLabelBright );
			m_pBuildLabelDim->SetVisible( !bBuildLabelBright );
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
int	CHudMenuSpyBuild::CalcCustomBuildMenuLayout( void ) const
{
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pLocalPlayer )
		return SPY_BUILDMENU_DEFAULT;

	int iMenu = SPY_BUILDMENU_DEFAULT;
	CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, iMenu, set_custom_buildmenu );
	return iMenu;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::InitBuildings()
{
	for( int i = 0; i < NUM_SPY_BUILDINGS; ++i )
	{
		m_Buildings[i] = g_kSpyBuildings[i];
	}

	ReplaceBuildings( m_Buildings );
	
	InvalidateLayout( true, true );
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CHudMenuSpyBuild::ReplaceBuildings( SpyConstructBuilding_t (&targetBuildings)[NUM_SPY_BUILDINGS] )
{
	C_TFPlayer *pLocalPlayer = C_TFPlayer::GetLocalTFPlayer();
	if ( !pLocalPlayer )
		return;

	int iOverrideType = -1;
	CALL_ATTRIB_HOOK_INT_ON_OTHER( pLocalPlayer, iOverrideType, override_engineer_object_type );

	CUtlVector< const SpyConstructBuildingReplacement_t* > vecReplacements;

	if ( iOverrideType >= 0 && iOverrideType < ARRAYSIZE( s_alternateSpyBuildings ) )
	{
		vecReplacements.AddToTail( &s_alternateSpyBuildings[iOverrideType] );
	}
	// add more replacement attributes here

	// verify the override data to make sure that they don't conflict with each other
	int iReplacedSlots = 0;
	int iDisabledSlots = 0;
	bool bReplaced = false;
	for ( int i = 0; i < vecReplacements.Count(); ++i )
	{
		const SpyConstructBuildingReplacement_t* pReplace = vecReplacements[i];
		int iReplacingSlots = pReplace->m_iReplacementSlots;
		int iDisablingSlots = pReplace->m_iDisableSlots;

		if ( iReplacedSlots & iReplacingSlots )
		{
			AssertMsg( 0, "Trying to replace the same engineer building slot multiple time" );
			continue;
		}

		if ( iReplacedSlots & iDisablingSlots )
		{
			AssertMsg( 0, "Trying to disable a replaced engineer building slot" );
			continue;
		}

		if ( iDisabledSlots & iReplacingSlots )
		{
			AssertMsg( 0, "Trying to replace a disabled slot" );
			continue;
		}
		
		// no conflict, replace the building
		for ( int j = 0; j < ARRAYSIZE( trapSlots ); ++j )
		{
			COMPILE_TIME_ASSERT( ARRAYSIZE( targetBuildings ) == ARRAYSIZE( trapSlots ) );
			if ( trapSlots[j] & iReplacingSlots )
			{
				targetBuildings[j] = pReplace->m_building;
			}
			else if ( trapSlots[j] & iDisablingSlots )
			{
				targetBuildings[j].m_bEnabled = false;
			}
		}

		iReplacedSlots |= iReplacingSlots;
		iDisabledSlots |= iDisablingSlots;
		bReplaced = true;
	}
}

//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CHudMenuSpyBuild::CanBuild( int iSlot )
{
	bool bInTraining = TFGameRules() && TFGameRules()->IsInTraining();
	if ( bInTraining == false )
	{
		int slot = iSlot - 1;
		if ( slot >= 0 && slot < NUM_SPY_BUILDINGS )
		{
			return m_Buildings[slot].m_bEnabled;
		}

		return false;
	}

	bool bCanBuild = true;
	switch ( iSlot )
	{
	case 1:
		{
			ConVarRef training_can_build_sentry( "training_can_build_sentry");
			bCanBuild = training_can_build_sentry.GetInt() != 0;
		}			
		break;
	case 2:
		{
			ConVarRef training_can_build_dispenser( "training_can_build_dispenser");
			bCanBuild = training_can_build_dispenser.GetInt() != 0;
		}
		break;
	case 3:
		{
			ConVarRef training_can_build_tele_entrance( "training_can_build_tele_entrance");
			bCanBuild = training_can_build_tele_entrance.GetInt() != 0;
		}
		break;
	case 4:
		{
			ConVarRef training_can_build_tele_exit( "training_can_build_tele_exit");
			bCanBuild = training_can_build_tele_exit.GetInt() != 0;
		}
		break;
	}
	return bCanBuild;
}
#endif // STAGING_ONLY

