//////////////////////////////////////////////////////////////////////////////
//
// Axon_BehaviourParams_GS2AttractorEnRoute.cpp
//
// Copyright (C) 2008 Rebellion. All Rights Reserved.
//
//////////////////////////////////////////////////////////////////////////////

// I N C L U D E S ///////////////////////////////////////////////////////////

// core
#include "Core/Asura.h"

#ifdef ASURA_USE_AXON

// header
#include "Behaviour/BehaviourParamsTypes/Axon_BehaviourParams_GS2AttractorEnRoute.h"

// asura
#include "AnimTemplates/Axon_Gamescene_AnimTemplate_System.h"
#include "ChunkSystem/Asura_Chunk_Stream.h"

// axon

// tools
#ifdef ASURA_TOOLS
#include "AnimTemplates/Tools_Mode_AnimTemplates.h"
#include "Entity/Locations/Tools_Entity_Node.h"
#endif

//////////////////////////////////////////////////////////////////////////////
//
// Axon_BehaviourParams_GS2AttractorEnRoute
//
//////////////////////////////////////////////////////////////////////////////

#ifdef ASURA_TOOLS
TOOLS_DECLARE_SHARED_PARAM( Asura_String, 0x60c15f48, GS2Attr_Param_AnimSetString ); // Asura_GetHashID( "GS2Attr_Param_AnimSetString" )
TOOLS_DECLARE_SHARED_PARAM( int,          0xcc05bc18, GS2Attr_Param_AnimSetInt );    // Asura_GetHashID( "GS2Attr_Param_AnimSetInt" )
TOOLS_DECLARE_SHARED_PARAM( bool,  0x42ae75b1, GS2Attr_Param_UseArrivalRange ); // Asura_GetHashID( "GS2Attr_Param_UseArrivalRange" )
TOOLS_DECLARE_SHARED_PARAM( float, 0xd179d4de, GS2Attr_Param_ArrivalRange );    // Asura_GetHashID( "GS2Attr_Param_ArrivalRange" )
#endif

Axon_BehaviourParams_GS2AttractorEnRoute::Axon_BehaviourParams_GS2AttractorEnRoute( const Axon_BehaviourParams_GS2AttractorEnRoute& xAttParams )
: PARENT( xAttParams )
, m_uAnimSet( xAttParams.m_uAnimSet )
, m_bUseArrivalRange( xAttParams.m_bUseArrivalRange )
, m_fArrivalRange( xAttParams.m_fArrivalRange )
{
}

Axon_BehaviourParams_GS2AttractorEnRoute::Axon_BehaviourParams_GS2AttractorEnRoute( const u_int uBehaviourType )
: PARENT( AXON_BP_TYPE_GS2_ATTRACTOR_ENROUTE, uBehaviourType )
, m_uAnimSet( uAXON_ANIMATION_SEQUENCE_ID_NONE )
, m_bUseArrivalRange( false )
, m_fArrivalRange( 0.0f )
{
}

bool Axon_BehaviourParams_GS2AttractorEnRoute::IsBaseOrDerivativeOf( const u_int uParamsType ) const
{
	return ( uParamsType == AXON_BP_TYPE_GS2_ATTRACTOR_ENROUTE ) ? true : PARENT::IsBaseOrDerivativeOf( uParamsType );
}

void Axon_BehaviourParams_GS2AttractorEnRoute::ReadFromChunkStream( Asura_Chunk_Stream& xStream )
{
	int iVersion;
	xStream >> iVersion;

	PARENT::ReadFromChunkStream( xStream );

	if ( iVersion == CURRENT_CHUNK_VERSION )
	{
		xStream >> m_uAnimSet;
		xStream >> m_bUseArrivalRange;
		xStream >> m_fArrivalRange;
	}
	else if ( iVersion == 0 )
	{
		xStream >> m_uAnimSet;
		xStream >> m_fArrivalRange;
		m_bUseArrivalRange = ( m_fArrivalRange > 0.005f );
	}
	else
	{
		Asura_Assertf( false, ( "Axon_BehaviourParams_GS2AttractorEnRoute::ReadFromChunkStream - unhandled chunk version (%d)", iVersion ) );
	}
}

void Axon_BehaviourParams_GS2AttractorEnRoute::WriteToChunkStream( Asura_Chunk_Stream& xStream ) const
{
	xStream << CURRENT_CHUNK_VERSION;

	PARENT::WriteToChunkStream( xStream );

	xStream << m_uAnimSet;
	xStream << m_bUseArrivalRange;
	xStream << m_fArrivalRange;
}

#ifdef ASURA_TOOLS
void Axon_BehaviourParams_GS2AttractorEnRoute::Render()
{
	extern void Render_Sphere( const Asura_Vector_3& xCentre, float fRadius, int iColour );

	PARENT::Render();

	if ( m_bUseArrivalRange && GetToolsNode()->IsGroupSelected() )
	{
		Render_Sphere( GetToolsNode()->Position, m_fArrivalRange, 0xff00ff00 );
	}
}

void Axon_BehaviourParams_GS2AttractorEnRoute::AddOverlayControls( Asura_Tabs_Dialog* pxTabsDialog, Asura_Vector_2& xOffset )
{
	PARENT::AddOverlayControls( pxTabsDialog, xOffset );

	Asura_Dialog* pxNewDialog = new Asura_Function_Dialog( "Anim Set: ", &g_xParam_GS2Attr_Param_AnimSetString, xOffset, PickAnimSet, reinterpret_cast< int >( this ) );
	pxTabsDialog->AddDialog( pxNewDialog );
	xOffset.y += Asura_Dialog::DefaultSpacing();

	pxNewDialog = new Asura_SharedTickbox_Dialog( "Use Arrival Range:", xOffset, &g_xParam_GS2Attr_Param_UseArrivalRange );
	pxNewDialog->SetHelpText( "If ticked the actor will pick a random point within the range to arrive at." );
	pxTabsDialog->AddDialog( pxNewDialog );
	xOffset.x += 15.0f;

	pxNewDialog = new Asura_Numerical_Dialog( "", xOffset, &g_xParam_GS2Attr_Param_ArrivalRange, 0.0f, 10000.0f, 0.25f, "%0.2f" );
	pxNewDialog->SetIsEnabledFunction( IsUsingRange, reinterpret_cast< int >( this ) );
	pxTabsDialog->AddDialog( pxNewDialog );
	xOffset.x -= 15.0f;
	xOffset.y += Asura_Dialog::DefaultSpacing();
}

void Axon_BehaviourParams_GS2AttractorEnRoute::AddFilesToExportList( List< Asura_String >& xNameList ) const
{
	PARENT::AddFilesToExportList( xNameList );

	// Add the animation files from the anim template to the export list.
	Axon_Gamescene_AnimTemplate* pxTemplate = Axon_Gamescene_AnimTemplate_System::GetAnimTemplateByID( m_uAnimSet );
	if ( pxTemplate )
	{
		pxTemplate->AddFilesToExportList( xNameList );
	}
}

bool Axon_BehaviourParams_GS2AttractorEnRoute::GetParameter( const Asura_Hash_ID uParamID, Tools_Parameter* pxParam ) const
{
	switch ( uParamID )
	{
		case g_uHash_GS2Attr_Param_AnimSetString:
		{
			if ( m_uAnimSet == uAXON_ANIMATION_SEQUENCE_ID_NONE )
			{
				pxParam->SetString( "*none*" );
			}
			else
			{
				const Axon_Gamescene_AnimTemplate* pxTemplate = Axon_Gamescene_AnimTemplate_System::GetAnimTemplateByID( m_uAnimSet );
				if ( pxTemplate )
				{
					pxParam->SetString( pxTemplate->m_xTemplateName );
				}
				else
				{
					pxParam->SetString( "NOT FOUND" );
				}
			}
			return true;
		}

		case g_uHash_GS2Attr_Param_AnimSetInt:
			// This is only ever set, not got, because of the way shared function dialogues work.
			return true;

		case g_uHash_GS2Attr_Param_UseArrivalRange:
			pxParam->SetBool( m_bUseArrivalRange );
			return true;

		case g_uHash_GS2Attr_Param_ArrivalRange:
			pxParam->SetFloat( m_fArrivalRange );
			return true;

		default:
			return PARENT::GetParameter( uParamID, pxParam );
	}
}

bool Axon_BehaviourParams_GS2AttractorEnRoute::SetParameter( const Asura_Hash_ID uParamID, const Tools_Parameter* pxParam )
{
	switch ( uParamID )
	{
		case g_uHash_GS2Attr_Param_AnimSetString:
			// This is only ever got, not set, because of the way shared function dialogues work.
			return true;

		case g_uHash_GS2Attr_Param_AnimSetInt:
			m_uAnimSet = pxParam->GetInt();
			if ( GetToolsNode()->IsSelected() )
			{
				GetToolsNode()->RequestRefreshOverlay();
			}
			GetToolsNode()->SetEntityModified();
			return true;

		case g_uHash_GS2Attr_Param_UseArrivalRange:
			m_bUseArrivalRange = pxParam->GetBool();
			if ( !m_bUseArrivalRange )
			{
				m_fArrivalRange = 0.0f;
			}
			GetToolsNode()->SetEntityModified();
			return true;

		case g_uHash_GS2Attr_Param_ArrivalRange:
			m_fArrivalRange = pxParam->GetFloat();
			GetToolsNode()->SetEntityModified();
			return true;

		default:
			return PARENT::SetParameter( uParamID, pxParam );
	}
}

bool Axon_BehaviourParams_GS2AttractorEnRoute::Verify( const bool bAutomatic )
{
	bool bOk = PARENT::Verify( bAutomatic );

	// Check if the anim set still exists.
	if ( m_uAnimSet != uAXON_ANIMATION_SEQUENCE_ID_NONE )
	{
		if ( !Axon_Gamescene_AnimTemplate_System::GetAnimTemplateByID( m_uAnimSet ) )
		{
			bOk = false;
			Tools_MessageLog::AddMessage( Tools_MessageLog::VERIFICATION, "Gamescene", new Tools_MessageLogAction_GotoEntity( GetToolsNode()->GetGuid() ),
				"GS2 attractor %u cannot find its anim set.", GetToolsNode()->GetGuid() );
		}
	}

	return bOk;
}

Axon_BehaviourParams* Axon_BehaviourParams_GS2AttractorEnRoute::Clone() const
{
	return new Axon_BehaviourParams_GS2AttractorEnRoute( *this );
}

void Axon_BehaviourParams_GS2AttractorEnRoute::PickAnimSet( int iThis )
{
	Axon_BehaviourParams_GS2AttractorEnRoute* pxThis = reinterpret_cast< Axon_BehaviourParams_GS2AttractorEnRoute* >( iThis );

	const u_int uTypeBitfield = (1 << AXON_ATT_LOOPINGMOVEMENT);
	u_int uSequenceID;
	if ( Tools_AnimTemplates::ChooseAnimTemplate( uSequenceID, uTypeBitfield, uAXON_ANIMATION_SEQUENCE_ID_NONE, pxThis->m_uAnimSet, true ) )
	{
		// Setting this will cause SetParameter to be called with this parameter hash on all selected objects.
		g_xParam_GS2Attr_Param_AnimSetInt.SetValue( uSequenceID );
	}
}

bool Axon_BehaviourParams_GS2AttractorEnRoute::IsUsingRange( int iThis )
{
	Axon_BehaviourParams_GS2AttractorEnRoute* pxThis = reinterpret_cast< Axon_BehaviourParams_GS2AttractorEnRoute* >( iThis );
	return ( pxThis->m_bUseArrivalRange );
}
#endif // ASURA_TOOLS

//////////////////////////////////////////////////////////////////////////////
//
// 
//
//////////////////////////////////////////////////////////////////////////////

#endif // ASURA_USE_AXON
