//========= Copyright Valve Corporation, All rights reserved. ============//
//
//
//=====================================================================================//
#include "cbase.h"
#include "c_physicsprop.h"
#include "portal_gamerules.h"
#include "igameevents.h"
#include "soundenvelope.h"
#include "beamdraw.h"


//#define RADIO_DEBUG_CLIENT


class C_Dinosaur_Signal : public C_BaseEntity
{
public:
	DECLARE_CLIENTCLASS();
	DECLARE_CLASS( C_Dinosaur_Signal, C_BaseEntity );

	char  m_szSoundName[128];
	float m_flInnerRadius;
	float m_flOuterRadius;
	int	  m_nSignalID;
};

IMPLEMENT_CLIENTCLASS_DT( C_Dinosaur_Signal, DT_DinosaurSignal, CDinosaurSignal )
	RecvPropString( RECVINFO(m_szSoundName) ), 
	RecvPropFloat( RECVINFO(m_flOuterRadius) ),
	RecvPropFloat( RECVINFO(m_flInnerRadius) ),
	RecvPropInt( RECVINFO(m_nSignalID) ),
END_RECV_TABLE()

class C_Portal_Dinosaur : public C_PhysicsProp
{
public:
	DECLARE_CLIENTCLASS();
	DECLARE_CLASS( C_Portal_Dinosaur, C_PhysicsProp );

				~C_Portal_Dinosaur( void );

	virtual void Spawn();
	virtual void Precache();
	virtual void ClientThink();
	virtual	int DrawModel( int flags );

	void ScanForSounds();
	void SetupSounds();

	CHandle<C_Dinosaur_Signal> m_hDinosaur_Signal;
	float	m_flOldBlend;
	bool	m_bAlreadyDiscovered;
	bool	m_bDinosaurExtinct;

	// Sound envelopes
	CSoundPatch		*m_pNormalSound;
	CSoundPatch		*m_pStaticSound;
	CSoundPatch		*m_pSignalSound;
};

IMPLEMENT_CLIENTCLASS_DT( C_Portal_Dinosaur, DT_PropDinosaur, CPortal_Dinosaur )
	RecvPropEHandle( RECVINFO( m_hDinosaur_Signal) ),
	RecvPropBool( RECVINFO(m_bAlreadyDiscovered) ),
END_RECV_TABLE()

void C_Portal_Dinosaur::Spawn()
{
	Precache();

	m_flOldBlend = 0.0f;
	BaseClass::Spawn();
	SetThink( &C_Portal_Dinosaur::ClientThink );
	SetNextClientThink( CLIENT_THINK_ALWAYS );
}

C_Portal_Dinosaur::~C_Portal_Dinosaur( void )
{
	if ( m_pNormalSound != NULL )
	{
		CSoundEnvelopeController::GetController().Shutdown( m_pNormalSound );
	}

	if ( m_pStaticSound != NULL )
	{
		CSoundEnvelopeController::GetController().Shutdown( m_pStaticSound );
	}

	if ( m_pSignalSound != NULL )
	{
		CSoundEnvelopeController::GetController().Shutdown( m_pSignalSound );
	}
}

void C_Portal_Dinosaur::Precache( void )
{
	PrecacheScriptSound( "Portal.room1_radio" );
	PrecacheScriptSound( "UpdateItem.Static" );
	PrecacheScriptSound( "UpdateItem.Dinosaur01" );
	PrecacheScriptSound( "UpdateItem.Dinosaur02" );
	PrecacheScriptSound( "UpdateItem.Dinosaur03" );
	PrecacheScriptSound( "UpdateItem.Dinosaur04" );
	PrecacheScriptSound( "UpdateItem.Dinosaur05" );
	PrecacheScriptSound( "UpdateItem.Dinosaur06" );
	PrecacheScriptSound( "UpdateItem.Dinosaur07" );
	PrecacheScriptSound( "UpdateItem.Dinosaur08" );
	PrecacheScriptSound( "UpdateItem.Dinosaur09" );
	PrecacheScriptSound( "UpdateItem.Dinosaur10" );
	PrecacheScriptSound( "UpdateItem.Dinosaur11" );
	PrecacheScriptSound( "UpdateItem.Dinosaur12" );
	PrecacheScriptSound( "UpdateItem.Dinosaur13" );
	PrecacheScriptSound( "UpdateItem.Dinosaur14" );
	PrecacheScriptSound( "UpdateItem.Dinosaur15" );
	PrecacheScriptSound( "UpdateItem.Dinosaur16" );
	PrecacheScriptSound( "UpdateItem.Dinosaur17" );
	PrecacheScriptSound( "UpdateItem.Dinosaur18" );
	PrecacheScriptSound( "UpdateItem.Dinosaur19" );
	PrecacheScriptSound( "UpdateItem.Dinosaur20" );
	PrecacheScriptSound( "UpdateItem.Dinosaur21" );
	PrecacheScriptSound( "UpdateItem.Dinosaur22" );
	PrecacheScriptSound( "UpdateItem.Dinosaur23" );
	PrecacheScriptSound( "UpdateItem.Dinosaur24" );
	PrecacheScriptSound( "UpdateItem.Dinosaur25" );
	PrecacheScriptSound( "UpdateItem.Dinosaur26" );
}

void C_Portal_Dinosaur::SetupSounds()
{
	CPASAttenuationFilter filter( this );

	if ( m_pNormalSound == NULL )
	{
		m_pNormalSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "Portal.room1_radio" );
		CSoundEnvelopeController::GetController().Play( m_pNormalSound, 0.0, PITCH_NORM );
	}

	if ( m_pStaticSound == NULL )
	{
		m_pStaticSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "UpdateItem.Static" );
		CSoundEnvelopeController::GetController().Play( m_pStaticSound, 0.0, PITCH_NORM );
	}

	if ( m_pSignalSound == NULL && 	m_hDinosaur_Signal.Get() != NULL )
	{
		m_pSignalSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), m_hDinosaur_Signal->m_szSoundName );
		//m_pSignalSound = CSoundEnvelopeController::GetController().SoundCreate( filter, entindex(), "UpdateItem.Signal" );
		CSoundEnvelopeController::GetController().Play( m_pSignalSound, 0.0, PITCH_NORM );
	}
}

void C_Portal_Dinosaur::ClientThink()
{
	SetupSounds();

	//if ( V_stristr( engine->GetLevelName(), "testchmb_a_00" ) != 0 )
	if ( 0 )//m_hDinosaur_Signal.Get() && m_hDinosaur_Signal.Get()->m_nSignalID == 0 )
	{
		// TODO:Play either morse code or special sstv content based on 
		// game account client state given from gc.
	}
	else
	{
		// On any other map, we scan for the partnered Dinosaur_Signal signal
		ScanForSounds();
	}

	if ( m_bDinosaurExtinct == false && m_bDinosaurExtinct != m_bAlreadyDiscovered )
		m_bDinosaurExtinct = m_bAlreadyDiscovered;
}

void C_Portal_Dinosaur::ScanForSounds()
{
	if ( m_hDinosaur_Signal.Get() == NULL )
	{
		AssertMsgOnce( 0, "Unpaired radio exists on this map." );
		return;
	}

	// How much of the real signal to blend in
	// 1.0 at > outerrad, 0.0 at < inner rad, blend when in between the two.
	float flRadiusDelta = fabs( m_hDinosaur_Signal.Get()->m_flOuterRadius - m_hDinosaur_Signal.Get()->m_flInnerRadius );
	float flDist = m_hDinosaur_Signal.Get()->GetAbsOrigin().DistTo( GetAbsOrigin() );

	float flOuterBlend = RemapValClamped( flDist, m_hDinosaur_Signal.Get()->m_flOuterRadius, m_hDinosaur_Signal.Get()->m_flOuterRadius-(flRadiusDelta*0.5f), 1.0f, 0.0f );
	float flInnerBlend = RemapValClamped( flDist, m_hDinosaur_Signal.Get()->m_flOuterRadius-(flRadiusDelta*0.5f), m_hDinosaur_Signal.Get()->m_flInnerRadius, 0.0f, 1.0f );
	flInnerBlend = Bias( flInnerBlend, 0.1f );

	if ( m_pNormalSound )
	{
		CSoundEnvelopeController::GetController().SoundChangeVolume( m_pNormalSound, flOuterBlend, 0.1f );
	}

	float flMidBlend = 0.0f;
	if ( m_pStaticSound )
	{
		if ( flOuterBlend <= 0.0f )
		{
			flMidBlend = RemapValClamped( flDist, m_hDinosaur_Signal.Get()->m_flOuterRadius-(flRadiusDelta*0.5f), m_hDinosaur_Signal.Get()->m_flInnerRadius, 1.0f, 0.0f );
		}
		else
		{
			flMidBlend = RemapValClamped( flDist, m_hDinosaur_Signal.Get()->m_flOuterRadius, m_hDinosaur_Signal.Get()->m_flOuterRadius-(flRadiusDelta*0.5f), 0.0f, 1.0f );
			flMidBlend = Bias( flMidBlend, 0.9f );
		}
		CSoundEnvelopeController::GetController().SoundChangeVolume( m_pStaticSound, flMidBlend, 0.1f );
	}

	if ( m_pSignalSound )
	{
		CSoundEnvelopeController::GetController().SoundChangeVolume( m_pSignalSound, flInnerBlend, 0.1f );
	}

#if defined ( RADIO_DEBUG_CLIENT )
	// Msg( "Dinosaur(%d) listening for signal... dist: %f, blend amt: %f\n", entindex(), flDist, flMidBlend );
#endif
	
	// If we've fully heard this signal, mark the achievement
	if ( flInnerBlend >= 1.0f && m_flOldBlend < 1.0f )
	{
		m_bDinosaurExtinct = true;
		int id = m_hDinosaur_Signal.Get()->m_nSignalID;

		IGameEvent *event = gameeventmanager->CreateEvent( "dinosaur_signal_found" );
		if ( event )
		{
			event->SetInt( "id", id );
			gameeventmanager->FireEvent( event );
		}
	}

	m_flOldBlend = flInnerBlend;
}

int C_Portal_Dinosaur::DrawModel( int flags )
{
	int nRet = BaseClass::DrawModel( flags );

	CMaterialReference	hMaterial;
	hMaterial.Init( "sprites/grav_light", TEXTURE_GROUP_CLIENT_EFFECTS );

	// Draw the sprite
	CMatRenderContextPtr pRenderContext( materials );
	pRenderContext->Bind( hMaterial, this );
	color32 color;
	color.r = ( m_bDinosaurExtinct ) ? 0 : 255;
	color.g = ( m_bDinosaurExtinct ) ? 255 : 0;
	color.b = 0;
	color.a = 128;

	Vector vForward, vRight, vUp;
	GetVectors( &vForward, &vRight, &vUp );
	Vector vOffset = GetAbsOrigin() + ( vForward * 4.0f ) + ( vUp * 1.85f );
	DrawSprite( vOffset, 6.0f, 6.0f, color );

	return nRet;
}