//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose:		Player for HL2.
//
//=============================================================================//

#include "cbase.h"
#include "hl2wars/c_hl2wars_player.h"
#include "hl2_gamerules.h"
#include <vgui_controls/Panel.h>
#include "inputsystem/ButtonCode.h"
#include "c_ai_basenpc.h"
#include "hl2wars/rts_shareddefs.h"
#include "hl2wars/c_rts_globalresource.h"
#include "hl2wars/c_rts_buildings.h"
#include "hl2wars/util_hl2wars_shared.h"

//#include "kbutton.h"

// Don't alias here
#if defined( CHL2Wars_Player )
#undef CHL2Wars_Player	
#endif

LINK_ENTITY_TO_CLASS( player, C_HL2Wars_Player );

IMPLEMENT_CLIENTCLASS_DT(C_HL2Wars_Player, DT_HL2Wars_Player, CHL2Wars_Player)
	RecvPropDataTable( RECVINFO_DT(m_HLWLocal),0, &REFERENCE_RECV_TABLE(DT_HLWLocal) ),

	RecvPropInt     (RECVINFO(m_iSlot)),		// gameroom specific
END_RECV_TABLE()

BEGIN_PREDICTION_DATA( C_HL2Wars_Player )
	DEFINE_PRED_TYPEDESCRIPTION( m_HLWLocal, C_HLWPlayerLocalData ),
END_PREDICTION_DATA()

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_HL2Wars_Player::C_HL2Wars_Player()
{
	m_nMouseButtons = 0;
	ClearLeftPressed();
	ClearRightPressed();
	m_pActivePanel = NULL;

	for( int i = 0; i < MAXSELECTED; i++ )
		m_hSelectedUnitsOld[i] = NULL;
	m_pSelectionBOld = NULL;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_HL2Wars_Player::~C_HL2Wars_Player( void )
{
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
C_HL2Wars_Player* C_HL2Wars_Player::GetLocalHL2WarsPlayer()
{
	return (C_HL2Wars_Player*)C_BasePlayer::GetLocalPlayer();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
//extern kbutton_t in_walk;
void C_HL2Wars_Player::ClientThink( void )
{
	UpdateSelected();

	// only send when we have new commands
	if( m_nNewRTSCommands != 0 || m_nNewRTSCommands2 != 0 )
	{
		engine->ServerCmd( VarArgs( "hl2wars_commands %d %d", m_nNewRTSCommands, m_nNewRTSCommands2 ) );	// update commands
		m_nNewRTSCommands = 0;	// clear for next input
		m_nNewRTSCommands2 = 0;	// clear for next input
	}

	BaseClass::ClientThink();
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::UpdateSelected()
{
	// first clear old or else this might conflict that are being moved around in the array.
	for( int i = 0; i < MAXSELECTED; i++ )
	{
		if( m_HLWLocal.m_hSelectedUnits[i] != m_hSelectedUnitsOld[i] )
		{
			// clear old
			if( m_HLWLocal.m_hSelectedUnits[i] == NULL )
			{
				m_hSelectedUnitsOld[i]->DestroySelectionCircle();
				m_hSelectedUnitsOld[i] = NULL;
			}
			else if( m_hSelectedUnitsOld[i] != NULL )
			{
				m_hSelectedUnitsOld[i]->DestroySelectionCircle();
				m_hSelectedUnitsOld[i] = NULL;
			}
		}
	}

	// clear old building if needed
	if( m_HLWLocal.m_hSelected != m_pSelectionBOld )
	{
		if( m_pSelectionBOld )
		{
			if( m_pSelectionBOld->IsRTSBrush() )
			{
				C_BuildingBrush *clear = dynamic_cast<C_BuildingBrush *> (m_pSelectionBOld.Get());
				if( clear )
					clear->SetSelected( false );
			}
			else if( m_pSelectionBOld->IsRTSModel() )
			{
				C_BaseBuildingModel *clearM = dynamic_cast<C_BaseBuildingModel *> (m_pSelectionBOld.Get());
				if( clearM && clearM->IsAlive() )
					clearM->SetSelected( false );
			}
			m_pSelectionBOld = NULL;
		}
	}

	// add the new or moved ones. A bit a shame we are first destroying then creating circles of units that are being moved around.
	for( int i = 0; i < MAXSELECTED; i++ )
	{
		if( m_HLWLocal.m_hSelectedUnits[i] != m_hSelectedUnitsOld[i] )
		{
			// just add the new to the old
			if( m_hSelectedUnitsOld[i] == NULL )
			{
				m_hSelectedUnitsOld[i] = m_HLWLocal.m_hSelectedUnits[i];
				m_HLWLocal.m_hSelectedUnits[i]->CreateSelectionCircle();
			}
		}
	}

	// buildings. If the old one is not the new one, it would have been cleared above.
	if( m_HLWLocal.m_hSelected != m_pSelectionBOld ) 
	{
		if( m_HLWLocal.m_hSelected->IsRTSBrush() )
		{
			C_BuildingBrush *pBuilding = dynamic_cast<C_BuildingBrush *> (m_HLWLocal.m_hSelected.Get() );
			if( pBuilding )
			{
				pBuilding->SetSelected( true );
				m_pSelectionBOld = pBuilding;

				return;
			}
		}
		else if( m_HLWLocal.m_hSelected->IsRTSModel() )
		{
			C_BaseBuildingModel *pBuildingM = dynamic_cast<C_BaseBuildingModel *> (m_HLWLocal.m_hSelected.Get() );
			if( pBuildingM && pBuildingM->IsAlive() )
			{
				pBuildingM->SetSelected( true );
				m_pSelectionBOld = pBuildingM;
			}
		}
	}
}

//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Purpose: Prediction
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::ClearSelection()
{
	for( int i = 0; i < MAXSELECTED; i++ )
		m_HLWLocal.m_hSelectedUnits[i] = NULL;
}

//-----------------------------------------------------------------------------
// Purpose: Prediction: just add the unit to the first free slot.
//			Units should be sended to the server at the same time.
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::AddToSelection( C_AI_BaseNPC *pNPC )
{
	for( int i = 0; i < MAXSELECTED; i++ )
	{
		if( m_HLWLocal.m_hSelectedUnits[i] == NULL )
		{
			m_HLWLocal.m_hSelectedUnits[i] = pNPC;
		}
	}
}

static ConVar cl_zoomspeed( "cl_zoomspeed", "2", FCVAR_ARCHIVE, "The zoom in speed." );

//-----------------------------------------------------------------------------
// Purpose: Input handling
//-----------------------------------------------------------------------------
bool C_HL2Wars_Player::CreateMove( float flInputSampleTime, CUserCmd *pCmd )
{
	if( m_fScrollForwardTimeOut > gpGlobals->curtime )
		pCmd->upmove -= 50 * cl_zoomspeed.GetFloat();

	if( m_fScrollBackwardsTimeOut > gpGlobals->curtime )
		pCmd->upmove += 50 * cl_zoomspeed.GetFloat();

	pCmd->m_nRTSButtons = m_nMouseButtons;

	// save for our usage client side. This won't be send back, because of the delay
	m_vecPickingRayMouse = pCmd->vecPickingRayMouse;

	// add direct move, if we are direct moving ( ... teleporting )
	if( m_bDirectMove )
	{
		pCmd->bDirectMove = m_bDirectMove;
		pCmd->vecMoveToPosition = m_vDirectMove;
		InvalidateDirectMove();
	}

	return BaseClass::CreateMove( flInputSampleTime, pCmd );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::ClearLeftPressed() 
{
	m_iMouse_x_pressed_left = -1;
	m_iMouse_y_pressed_left = -1;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::ClearRightPressed() 
{
	m_iMouse_x_pressed_right = -1;
	m_iMouse_y_pressed_right = -1;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
bool C_HL2Wars_Player::ReleaseActivePanel( vgui::MouseCode code )
{
	if( !m_pActivePanel )
		return false;

	m_pActivePanel->OnMouseReleased( code );
	m_pActivePanel = NULL;
	return true;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::SetActivePanel( vgui::Panel *panel)
{
	m_pActivePanel = panel;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::SetDirectMove( Vector position )
{
	m_bDirectMove = true;
	m_vDirectMove = position;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::InvalidateDirectMove()
{
	m_bDirectMove = false;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::UpdatePressedPosition()
{
	UTIL_MouseGroundPos( Weapon_ShootPosition(), m_vecPickingRayMouse, this, &m_vPressedPosition, &m_vPressedNormal );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::UpdateReleasedPosition()
{
	UTIL_MouseGroundPos( Weapon_ShootPosition(), m_vecPickingRayMouse, this, &m_vReleasedPosition, &m_vReleasedNormal );
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void C_HL2Wars_Player::UpdateCurPosition()
{
	UTIL_MouseGroundPos( Weapon_ShootPosition(), m_vecPickingRayMouse, this, &m_vCurPosition, &m_vCurNormal );
}