//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Utility code.
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"
#include "hl2wars/c_util_hl2wars.h"
#include "c_ai_basenpc.h"
#include "hl2wars/c_hl2wars_player.h"
//#include "hl2wars/rts_tracefilter.h"
#include "view.h"

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

void UTIL_RetrieveGroundPos( Vector *pVecPickingRay, Vector *position, Vector *normal )
{
	// get local player
	C_HL2Wars_Player *pPlayer = C_HL2Wars_Player::GetLocalHL2WarsPlayer();
	if( !pPlayer )
		return;

	// Check if the mouse points to a npc, if so, return the npc
    trace_t tr;
    Vector forward;
    AngleVectors(pPlayer->EyeAngles(),&forward);	//Get the forward vector frow our own eye angles.
    
	//CTraceFilterRTS TraceFiler( pPlayer );
	//CTraceFilterRTS *pTraceFiler = &TraceFiler;

    UTIL_TraceLine(pPlayer->Weapon_ShootPosition(),pPlayer->Weapon_ShootPosition() + (*pVecPickingRay *  8192), MASK_SOLID, pPlayer, 0,&tr);

	// hit ground?
    if ( tr.DidHitWorld() || tr.IsDispSurface())//If we hit the ground, return the position
    {
		if( normal )
			VectorCopy( tr.plane.normal, *normal );	// update normal
		if( position )
  			VectorCopy( tr.endpos, *position );
    }
	else if( tr.m_pEnt ) {
		if( normal )
			VectorCopy( tr.plane.normal, *normal );	// update normal
		if( position )
			VectorCopy( tr.endpos, *position );
	}
}

//-----------------------------------------------------------------------------
// Purpose: Get the angle of the mouse pointer
//-----------------------------------------------------------------------------
Vector UTIL_GetCommanderAim( int p_iMouseX, int p_iMouseY )
{
	C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer();
	if ( !pPlayer )
		return Vector( 0, 0, 0 );

	float fov = pPlayer->GetFOV();
	float dx, dy;
	float c_x, c_y;
	float dist, fixdist;
	// First, we need the aspect as float!
	float aspect = (float)ScreenWidth() / 
		(float)ScreenHeight();

	// Then we need to calculate the difference 
	// between a 4:3 aspect and our current aspect
	aspect = ( 4.0f / 3.0f ) / aspect;

	Vector vecPickingRay;

	c_x = ScreenWidth() / 2;
	c_y = ScreenHeight() / 2;

	dx = ((float)p_iMouseX - c_x) / aspect;

	// Invert Y
	dy = (c_y - (float)p_iMouseY) / aspect;

	// Convert view plane distance
	fixdist = tan( M_PI * fov / 360.0 );
	dist = c_x / fixdist;

	// Offset forward by view plane distance, 
	// and then by pixel offsets
	vecPickingRay = (MainViewForward() * dist) 
		+ (MainViewRight() * dx) 
		+ (MainViewUp() * dy);

	// Convert to unit vector
	VectorNormalize( vecPickingRay );

	return vecPickingRay;
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
void UTIL_CreatePickingRay( float x, float y, int w, int h, Vector& org, Vector& forward ) 
{ 
	// Remap x and y into -1 to 1 normalized space 
	float xf, yf; 
	xf = ( 2.0f * x / (float)(w-1) ) - 1.0f; 
	yf = ( 2.0f * y / (float)(h-1) ) - 1.0f; 

	// Flip y axis 
	yf = -yf; 

	const VMatrix &worldToScreen = engine->WorldToScreenMatrix(); 
	VMatrix screenToWorld; 
	MatrixInverseGeneral( worldToScreen, screenToWorld ); 

	// Create two points at the normalized mouse x, y pos and at the near and far z planes (0 and 1 depth) 
	Vector v1, v2; 
	v1.Init( xf, yf, 0.0f ); 
	v2.Init( xf, yf, 1.0f ); 

	Vector o2; 
	// Transform the two points by the screen to world matrix 
	screenToWorld.V3Mul( v1, org ); // ray start origin 
	screenToWorld.V3Mul( v2, o2 ); // ray end origin 
	VectorSubtract( o2, org, forward ); 
	forward.NormalizeInPlace(); 
} 

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
const char *UTIL_GetColorName( int color )
{
	switch( color )
	{
	case GRCOLOR_NONE:
		return "";
	case GRCOLOR_ORANGE:
		return "Orange";
	case GRCOLOR_BLUE:
		return "Blue";
	case GRCOLOR_CYAN:
		return "Cyan";
	case GRCOLOR_GREEN:
		return "Green";
	case GRCOLOR_RED:
		return "Red";
	default:
		return "Invalid color!";
	}
}

//-----------------------------------------------------------------------------
// Purpose: 
//-----------------------------------------------------------------------------
const char *UTIL_GetFactionName( int faction )
{
	switch( faction )
	{
	case FACTION_REBEL:
		return "Rebels";
	case FACTION_COMBINE:
		return "Combine";
	default:
		return "Invalid faction!";
	}
}