//========= Copyright © 1996-2005, Sander Corporation, All rights reserved. ============//
//
// Purpose: c_rts_building.cpp
//
// $NoKeywords: $
//=============================================================================//

#include "cbase.h"
#include "hl2wars/c_rts_buildings.h"
#include <KeyValues.h>
#include "hl2wars/c_rts_globalresource.h"

#include "tempent.h"
#include "c_te_legacytempents.h"
#include "sprite.h"

#include "fx_quad.h"

// link data table DT_Myentity to client class and map variables (RecvProps)
IMPLEMENT_CLIENTCLASS_DT( C_BuildingBrush, DT_BuildingBrush, CBuildingBrush )
	RecvPropArray3( RECVINFO_ARRAY(m_iTypesQueue), RecvPropInt( RECVINFO( m_iTypesQueue[0] ) ) ),
	RecvPropArray3( RECVINFO_ARRAY(m_iQueueAmount), RecvPropInt( RECVINFO( m_iQueueAmount[0] ) ) ),
	RecvPropFloat( RECVINFO( m_fBuildTimeMax ) ),
	RecvPropArray3( RECVINFO_ARRAY(m_iTypesAbilities), RecvPropInt( RECVINFO( m_iTypesAbilities[0] ) ) ),

	// receive normal stuff
	RecvPropInt( RECVINFO( m_iOwnerShip ) ),
	RecvPropFloat( RECVINFO( m_fBuildTime ) ),
	RecvPropVector	(RECVINFO(m_vOwnerShipIconTarget)),

	// rallypoint 
	RecvPropVector(RECVINFO( m_vRallyPoint )),
END_RECV_TABLE()

IMPLEMENT_CLIENTCLASS_DT( C_BuildingModel, DT_BuildingModel, CBuildingModel )
	// build info
	RecvPropArray3( RECVINFO_ARRAY(m_iTypesQueue), RecvPropInt( RECVINFO( m_iTypesQueue[0] ) ) ),
	RecvPropArray3( RECVINFO_ARRAY(m_iQueueAmount), RecvPropInt( RECVINFO( m_iQueueAmount[0] ) ) ),
	RecvPropFloat( RECVINFO( m_fBuildTimeMax ) ),
	RecvPropArray3( RECVINFO_ARRAY(m_iTypesAbilities), RecvPropInt( RECVINFO( m_iTypesAbilities[0] ) ) ),
	RecvPropFloat( RECVINFO( m_fBuildTime ) ),

	// rallypoint 
	RecvPropVector(RECVINFO( m_vRallyPoint )),
END_RECV_TABLE()

// a list of objective env to search quickly
C_EntityClassList<C_BuildingBrush> g_BuildingBrushList;
C_BuildingBrush *C_EntityClassList<C_BuildingBrush>::m_pClassList = NULL;
C_BuildingBrush *GetBuildingBrushList()
{
	return g_BuildingBrushList.m_pClassList;
}

extern C_EntityClassList<C_BuildingBrush> g_BuildingBrushList; 

C_BuildingBrush::C_BuildingBrush() 
{
	g_BuildingBrushList.Insert( this );
	m_pRallyPoint = NULL;
}

C_BuildingBrush::~C_BuildingBrush() 
{
	g_BuildingBrushList.Remove( this );
}

void C_BuildingBrush::Spawn() 
{
	BaseClass::Spawn();
	
	/*Msg("Creating sprite \n");
	m_hIcon = CREATE_ENTITY( C_Sprite, "env_sprite" );
	//m_hIcon->SetRenderMode();
	//m_hIcon->SetRenderColor( 255, 255, 255 );
	if ( m_hIcon == NULL )
		return;

	Msg("We created a sprite, setting up now\n");
	//m_hIcon->SetAbsOrigin(m_vOwnerShipIconTarget);
	//m_hIcon->m_bVisibleLaserDot = bVisibleDot;
	///m_hIcon->SetMoveType( MOVETYPE_NONE );
	//m_hIcon->AddSolidFlags( FSOLID_NOT_SOLID );
	//m_hIcon->AddEffects( EF_NOSHADOW );
	//UTIL_SetSize( pLaserDot, vec3_origin, vec3_origin );
	//m_hIcon->SetSize( vec3_origin, vec3_origin );

	//Create the graphic
	m_hIcon->SpriteInit( "vgui/icons/icon_barracks.vmt", m_vOwnerShipIconTarget );

	//m_hIcon->SetName( AllocPooledString("TEST") );

	m_hIcon->SetTransparency( kRenderGlow, 255, 255, 255, 255, kRenderFxNoDissipation );
	m_hIcon->SetScale( 20.0f );

	//m_hIcon->SetOwnerEntity( this );

	//pLaserDot->SetContextThink( &CLaserDot::LaserThink, gpGlobals->curtime + 0.1f, g_pLaserDotThink );
	m_hIcon->SetSimulatedEveryTick( true );

	m_hIcon->Spawn();
	m_hIcon->TurnOn();*/

	// fuck client sided sprites

}

void C_BuildingBrush::UpdateOnRemove()
{
	BaseClass::UpdateOnRemove();

	if( m_pRallyPoint )
	{
		m_pRallyPoint->die = NULL;
		m_pRallyPoint = NULL;
	}
}

void C_BuildingBrush::OnRestore()
{
	BaseClass::OnRestore();

	if( m_bSelected )
	{
		if( !m_pRallyPoint )
		{
			MDLCACHE_CRITICAL_SECTION();
			struct model_t *m_pRallyModel = (model_t *) engine->LoadModel( "props/spawn_flag.mdl" );
			m_pRallyPoint = tempents->SpawnTempModel( m_pRallyModel, m_vRallyPoint, GetAbsAngles(), Vector( 0.0f, 0.0f, 0.0f), 1, FTENT_NEVERDIE );
		}
		m_pRallyPoint->RemoveEffects( EF_NODRAW );
	}
}

void C_BuildingBrush::OnDataChanged( DataUpdateType_t type )
{
	BaseClass::OnDataChanged( type );

	if( m_bSelected && m_pRallyPoint )
		m_pRallyPoint->SetAbsOrigin(m_vRallyPoint);
}

void C_BuildingBrush::SetSelected( bool selected )
{
	m_bSelected = selected;
	SetDrawSelection(m_bSelected);

	if( selected )
	{
		if( !m_pRallyPoint )
		{
			MDLCACHE_CRITICAL_SECTION();
			struct model_t *m_pRallyModel = (model_t *) engine->LoadModel( "models/props/spawn_flag.mdl" );
			m_pRallyPoint = tempents->SpawnTempModel( m_pRallyModel, m_vRallyPoint, GetAbsAngles(), Vector( 0.0f, 0.0f, 0.0f), 1, FTENT_NEVERDIE );
		}
		m_pRallyPoint->RemoveEffects( EF_NODRAW );

		// draw a disappearing circle around it
		const Vector color = Vector(0.0f, 1.0f, 0.0f);
		Vector up = Vector( 0, 0, 1 );

		FX_AddQuad(m_vRallyPoint + Vector(0.0f, 0.0f, 2.0f ), up, 40.0f, 0.0f, 4.5f, 0.0f, 255.0f, 100.0f, 
			0.0f, 0.0f, color, 1.0f, QUAD_TO_SELECT, 0);
	}
	else
	{
		// if we set state to false, we should have set state to true earlier. So we must have a rallypoint model.
		Assert(m_pRallyPoint);
		if( m_pRallyPoint )
		{
			m_pRallyPoint->AddEffects( EF_NODRAW );
		}
	}
}

//-----------------------------------------------------------------------------
// Purpose:  Called when the mouse starts hovering at the building
//-----------------------------------------------------------------------------
void C_BuildingBrush::OnCursorEntered()
{
	if( !IsSelected() )
		SetDrawSelection( true );
}

color32 C_BuildingBrush::GetColor()
{
	Vector color = g_RTSR->GetColor255( GetOwnerShip() );
	color32 color32clr = { color.x, color.y, color.z, 200 };
	return color32clr;
}
const char *C_BuildingBrush::GetUnitType( int unit_index )
{
	return g_RTSR->GetUnitType(unit_index);
}

// ##################################################################################
//	>> Building model implementation
//
// ##################################################################################

C_BuildingModel::C_BuildingModel()
{
	m_pRallyPoint = NULL;
}

void C_BuildingModel::Spawn() 
{
	BaseClass::Spawn();
}

void C_BuildingModel::UpdateOnRemove()
{
	BaseClass::UpdateOnRemove();

	if( m_pRallyPoint )
	{
		m_pRallyPoint->die = NULL;
		m_pRallyPoint = NULL;
	}
}

void C_BuildingModel::OnRestore()
{
	BaseClass::OnRestore();

	if( m_bSelected )
	{
		if( !m_pRallyPoint )
		{
			MDLCACHE_CRITICAL_SECTION();
			struct model_t *m_pRallyModel = (model_t *) engine->LoadModel( "props/spawn_flag.mdl" );
			m_pRallyPoint = tempents->SpawnTempModel( m_pRallyModel, m_vRallyPoint, GetAbsAngles(), Vector( 0.0f, 0.0f, 0.0f), 1, FTENT_NEVERDIE );
		}
		m_pRallyPoint->RemoveEffects( EF_NODRAW );
	}
}

void C_BuildingModel::OnDataChanged( DataUpdateType_t type )
{
	BaseClass::OnDataChanged( type );

	if( m_bSelected && m_pRallyPoint )
		m_pRallyPoint->SetAbsOrigin(m_vRallyPoint);
}

void C_BuildingModel::SetSelected( bool selected )
{
	BaseClass::SetSelected(selected);

	if( selected )
	{
		if( !m_pRallyPoint )
		{
			MDLCACHE_CRITICAL_SECTION();
			struct model_t *m_pRallyModel = (model_t *) engine->LoadModel( "models/props/spawn_flag.mdl" );
			m_pRallyPoint = tempents->SpawnTempModel( m_pRallyModel, m_vRallyPoint, GetAbsAngles(), Vector( 0.0f, 0.0f, 0.0f), 1, FTENT_NEVERDIE );
		}
		m_pRallyPoint->RemoveEffects( EF_NODRAW );
		m_pRallyPoint->SetAbsOrigin(m_vRallyPoint);

		// draw a disappearing circle around it
		const Vector color = Vector(0.0f, 1.0f, 0.0f);
		Vector up = Vector( 0, 0, 1 );

		FX_AddQuad(m_vRallyPoint + Vector(0.0f, 0.0f, 2.0f ), up, 40.0f, 0.0f, 4.5f, 0.0f, 255.0f, 100.0f, 
			0.0f, 0.0f, color, 1.0f, QUAD_TO_SELECT, 0);
	}
	else
	{
		// if we set state to false, we should have set state to true earlier. So we must have a rallypoint model.
		Assert(m_pRallyPoint);
		if( m_pRallyPoint )
		{
			m_pRallyPoint->AddEffects( EF_NODRAW );
		}
	}
}