/* ***** BEGIN LICENSE BLOCK *****
Version: MPL 1.1/LGPL 2.1/GPL 2.0

The contents of this file are subject to the Mozilla Public License Version 
1.1 (the "License"); you may not use this file except in compliance with
...
for the specific language governing rights and limitations under the
License.

The Original Code is for Luminous Forts.

The Initial Developer of the Original Code is Hekar Khani.
Portions created by the Hekar Khani are Copyright (C) 2010
Hekar Khani. All Rights Reserved.

Contributor(s):
  Hekar Khani <hekark@gmail.com>

Alternatively, the contents of this file may be used under the terms of
either of the GNU General Public License Version 2 or later (the "GPL"),
...
the terms of any one of the MPL, the GPL or the LGPL.

***** END LICENSE BLOCK ***** */


/*===============================================================
	Client
	HUD Element

	Displays the position of the blue and red flag in the map.

	Last Updated April 1, 2010
=================================================================*/


#include "cbase.h"
#include <vgui/ISurface.h>
#include "c_sdk_player.h"
#include "c_team.h"
#include "c_playerresource.h"

#include "ClassicGameRules.h"
#include "Hud_FlagPos.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"


ConVar lf_hud_flagpos_min( "lf_hud_flagpos_min", "16", FCVAR_REPLICATED, "The minimum width/height of the flag marker" );
ConVar lf_hud_flagpos_max( "lf_hud_flagpos_max", "28", FCVAR_REPLICATED, "The maximum width/height of the flag marker" );
ConVar lf_hud_flagpos_scale_divider( "lf_hud_flagpos_scale_divider", "1300", FCVAR_REPLICATED, "Divides the distance from a the flag with this number" );

//
//	Name: CHudFlagLocations
//	Author: Hekar Khani
//	Description: Displays locations of flags on the HUD
//				(as a marker translating from a 3D pos to 2D pos)
//	Notes: 
//
DECLARE_HUDELEMENT( CHudFlagLocations );

CHudFlagLocations::CHudFlagLocations( const char *pElementName ) : 
	CModHudElement( pElementName, HUDELEM_FLAGPOS ), BaseClass( NULL, "HudFlagLocations" )
{
	SetHiddenBits( HIDEHUD_HEALTH | HIDEHUD_PLAYERDEAD | HIDEHUD_NEEDSUIT | HIDEHUD_BUILDPHASE );
	vgui::Panel *pParent = g_pClientMode->GetViewport();
	SetParent( pParent );

	SetVisible( true );
	SetEnabled( true );

	m_BlueTexture = NULL;
	m_RedTexture = NULL;

	m_bNeedsUpdate = false;
}

void CHudFlagLocations::VidInit( void )
{
	if ( !m_BlueTexture )
	{
		m_BlueTexture = gHUD.GetIcon( "flag_icon_blue" );
		if ( !m_BlueTexture )
		{
			Error( "Failed to load flag_maker_blue\n" );
		}
	}

	if ( !m_RedTexture )
	{
		m_RedTexture = gHUD.GetIcon( "flag_icon_red" );
		if ( !m_RedTexture )
		{
			Error( "Failed to load flag_maker_red\n" );
		}
	}
}

bool CHudFlagLocations::ShouldDraw()
{
	C_SDKPlayer *pPlayer = C_SDKPlayer::GetLocalSDKPlayer();
	if ( !pPlayer )
		return false;
	if ( pPlayer->State_Get() != STATE_ACTIVE )
		return false;
	if ( g_pGameRules->GetGameModeMask() & GAMEMODE_CLASSIC )
	{
		if ( ClassicGameRules()->GetCurrentPhaseID() == PHASE_BUILD )
		{
			return false;
		}
	}

	return CModHudElement::ShouldDraw();
}

void CHudFlagLocations::ApplySchemeSettings( vgui::IScheme* scheme )
{
	BaseClass::ApplySchemeSettings( scheme );
	SetPaintBackgroundEnabled( false );
	m_hFont = scheme->GetFont( "HudFlagLocations", true );
}

void CHudFlagLocations::Paint()
{
	C_SDKPlayer *pLocalPlayer = C_SDKPlayer::GetLocalSDKPlayer();

	if ( !pLocalPlayer )
		return;

	if ( !m_BlueTexture )
	{
		return;
	}

	if ( !m_RedTexture )
	{
		return;
	}

	for ( int teamnumber = SDK_TEAM_BLUE; teamnumber <= SDK_TEAM_RED; teamnumber++ )
	{
		int x, y, length, alpha;

		Vector v = GetFlagLocation( teamnumber, pLocalPlayer );

		if( InView( pLocalPlayer, v ) )
		{
			length = ( v - pLocalPlayer->GetAbsOrigin() ).Length();

			if( length > 6000 )
			{
				alpha = 6255 - length;

				if ( alpha < 0 )
				{
					alpha = 0;
				}
			}
			else
			{
				alpha = 255;
			}

			GetVectorInScreenSpace( v, x, y, NULL );

			const float divider = lf_hud_flagpos_scale_divider.GetFloat();
			const float width = clamp( m_BlueTexture->EffectiveWidth( length / divider ), lf_hud_flagpos_min.GetFloat(), lf_hud_flagpos_max.GetFloat() );
			const float height = clamp( m_BlueTexture->EffectiveHeight( length / divider ), lf_hud_flagpos_min.GetFloat(), lf_hud_flagpos_max.GetFloat() );

			//set the indicator font texture
			if ( teamnumber == SDK_TEAM_BLUE )
			{
				if ( m_BlueTexture )
				{
					m_BlueTexture->DrawSelf( x - ( width / 2 ), y - ( height / 2 ), width, height, GetTeamColor( teamnumber ) );
				}
			}
			else if ( teamnumber == SDK_TEAM_RED )
			{
				if ( m_RedTexture )
				{
					m_RedTexture->DrawSelf( x - ( width / 2 ), y - ( height / 2 ), width, height, GetTeamColor( teamnumber ) );
				}
			}

			int meters = length / 40; //turn units in to meters (1 unit = 1 inch)

			wchar_t newText[32];
			_snwprintf( newText, sizeof( newText )/ sizeof( wchar_t ), L"%dm", meters );
			vgui::surface()->DrawSetTextFont( m_hFont );
			vgui::surface()->DrawSetTextColor( Color( 255, 255, 255, alpha ));
			vgui::surface()->DrawSetTextPos( x - 17, y + 15 );
			vgui::surface()->DrawPrintText( newText, wcslen( newText ));		}
	}
}

Vector CHudFlagLocations::GetFlagLocation( int team, C_SDKPlayer *pLocalPlayer )
{
	return ( team == SDK_TEAM_BLUE ) ? m_vBlueLocation : m_vRedLocation;
}

void CHudFlagLocations::UpdateFlagPosition( int Team, const Vector& Pos )
{
	m_bNeedsUpdate = true;
	switch ( Team )
	{
	case SDK_TEAM_BLUE:
		m_vBlueLocation = Pos;
		break;
	case SDK_TEAM_RED:
		m_vRedLocation = Pos;
		break;
	default:
		m_bNeedsUpdate = false;
		break;
	}
}

PrivateMethod bool CHudFlagLocations::InView( C_BasePlayer *pLocalPlayer, Vector v )
{
	// Clip text that is far away
	if( ( pLocalPlayer->GetAbsOrigin() - v ).LengthSqr() > 90000000 ) 
		return false;

	// Clip text that is behind the client
	Vector clientForward;
	pLocalPlayer->EyeVectors( &clientForward );

	Vector toText = v - pLocalPlayer->GetAbsOrigin();
	float  dotPr = DotProduct( clientForward, toText );

	if ( dotPr < 0 ) 
		return false;

	return true;
}
