struct DEBUG_VisualRecord
{
	var layerIDs : array< Uint32 >;
	var puppet : weak< ScriptedPuppet >;
	var infiniteDuration : Bool;
	var showDuration : Float;
}

class DEBUG_VisualizerComponent extends ScriptableComponent
{
	private var records : array< DEBUG_VisualRecord >;
	private var offsetCounter : Int32;
	default offsetCounter = 0;
	private var timeToNextUpdate : Float;
	private var processedRecordIndex : Int32;
	private var showWeaponsStreaming : Bool;
	private const var TICK_TIME_DELTA : Float;
	default TICK_TIME_DELTA = 0.01f;
	private const var TEXT_SCALE_NAME : Float;
	default TEXT_SCALE_NAME = 3.f;
	private const var TEXT_SCALE_ATTITUDE : Float;
	default TEXT_SCALE_ATTITUDE = 2.f;
	private const var TEXT_SCALE_IMMORTALITY_MODE : Float;
	default TEXT_SCALE_IMMORTALITY_MODE = 1.f;
	private const var TEXT_TOP : Float;
	default TEXT_TOP = 2.3f;
	private const var TEXT_OFFSET : Float;
	default TEXT_OFFSET = 0.2f;

	public function VisualizePuppets( const pups : ref< array< ScriptedPuppet > >, infDuration : Bool, duration : Float )
	{
		var rec : DEBUG_VisualRecord;
		var i, j : Int32;
		var alreadyExists : Bool;
		if( ( pups.Size() == 0 ) || ( !( infDuration ) && ( duration <= 0.0 ) ) )
		{
			return;
		}
		for( i = 0; i < pups.Size(); i += 1 )
		{
			alreadyExists = false;
			for( j = 0; j < records.Size(); j += 1 )
			{
				if( records[ j ].puppet == pups[ i ] )
				{
					records[ j ].infiniteDuration = infDuration;
					records[ j ].showDuration = duration;
					alreadyExists = true;
					break;
				}
			}
			if( !( alreadyExists ) )
			{
				rec.puppet = pups[ i ];
				rec.infiniteDuration = infDuration;
				rec.showDuration = duration;
				records.PushBack( rec );
			}
		}
		if( !( IsEnabled() ) )
		{
			Toggle( true );
		}
	}

	private function VisualizePuppetInternal( index : Int32 )
	{
		offsetCounter = 0;
		processedRecordIndex = index;
		VisualizeDisplayName( TEXT_SCALE_NAME );
		VisualizeAttitude( TEXT_SCALE_ATTITUDE );
		VisualizeImmortality( TEXT_SCALE_IMMORTALITY_MODE );
	}

	public function ClearPuppetVisualization()
	{
		var i : Int32;
		for( i = records.Size() - 1; i >= 0; i -= 1 )
		{
			ClearPuppet( i );
		}
	}

	private function ClearPuppet( index : Int32 )
	{
		var i : Int32;
		var dvs : DebugVisualizerSystem;
		if( records.Size() == 1 )
		{
			Toggle( false );
		}
		dvs = GameInstance.GetDebugVisualizerSystem( GetOwner().GetGame() );
		for( i = 0; i < records[ index ].layerIDs.Size(); i += 1 )
		{
			dvs.ClearLayer( records[ index ].layerIDs[ i ] );
		}
		records.Erase( index );
	}

	private function GetNextOffset() : Vector4
	{
		var offset : Vector4;
		offset = Vector4( 0.0, 0.0, TEXT_TOP - ( TEXT_OFFSET * ( ( Float )( offsetCounter ) ) ), 0.0 );
		offsetCounter += 1;
		return offset;
	}

	private function VisualizeDisplayName( scale : Float )
	{
		ShowText( GetNextOffset(), records[ processedRecordIndex ].puppet.GetDisplayName(), Color( 255, 255, 0, 255 ), scale );
	}

	private function VisualizeImmortality( scale : Float )
	{
		var type : gameGodModeType;
		var hasImmortality : Bool;
		var color : Color;
		var str : String;
		hasImmortality = GetImmortality( records[ processedRecordIndex ].puppet, type );
		if( !( hasImmortality ) )
		{
			str = StrUpper( "No Immortality" );
			color = Color( 255, 0, 0, 255 );
		}
		else
		{
			str = "" + type;
			switch( type )
			{
				case gameGodModeType.Immortal:
					color = Color( 0, 128, 0, 255 );
				break;
				case gameGodModeType.Invulnerable:
					color = Color( 0, 255, 0, 255 );
				break;
				default:
					break;
			}
		}
		ShowText( GetNextOffset(), str, color, scale );
	}

	private function VisualizeAttitude( scale : Float )
	{
		var attitude : EAIAttitude;
		var attitudeStr : String;
		var attitudeColor : Color;
		var player : PlayerPuppet;
		player = GetPlayer( records[ processedRecordIndex ].puppet.GetGame() );
		attitude = GameObject.GetAttitudeBetween( player, records[ processedRecordIndex ].puppet );
		attitudeStr = EnumValueToString( "EAIAttitude", ( ( Int64 )( attitude ) ) );
		attitudeStr = StrUpper( StrReplace( attitudeStr, "AIA_", "" ) );
		switch( attitude )
		{
			case EAIAttitude.AIA_Hostile:
				attitudeColor = Color( 255, 0, 0, 255 );
			break;
			case EAIAttitude.AIA_Neutral:
				attitudeColor = Color( 190, 190, 190, 255 );
			break;
			case EAIAttitude.AIA_Friendly:
				attitudeColor = Color( 0, 255, 0, 255 );
			break;
			default:
				break;
		}
		ShowText( GetNextOffset(), attitudeStr, attitudeColor, scale );
	}

	private function ShowText( offset : Vector4, const str : ref< String >, color : Color, scale : Float )
	{
		var layerID : Uint32;
		var dvs : DebugVisualizerSystem;
		dvs = GameInstance.GetDebugVisualizerSystem( records[ processedRecordIndex ].puppet.GetGame() );
		layerID = dvs.DrawText3D( records[ processedRecordIndex ].puppet.GetWorldPosition() + offset, str, color, MaxF( TICK_TIME_DELTA, 0.05 ) );
		dvs.SetScale( layerID, Vector4( scale, scale, scale, 0.0 ) );
		records[ processedRecordIndex ].layerIDs.PushBack( layerID );
	}

	public export function OnGameAttach()
	{
		Toggle( false );
	}

	public function OnUpdate( dt : Float )
	{
		var i : Int32;
		if( timeToNextUpdate <= 0.0 )
		{
			timeToNextUpdate = TICK_TIME_DELTA;
			for( i = records.Size() - 1; i >= 0; i -= 1 )
			{
				if( !( records[ i ].infiniteDuration ) && ( records[ i ].showDuration <= 0.0 ) )
				{
					ClearPuppet( i );
					continue;
				}
				if( !( records[ i ].infiniteDuration ) )
				{
					records[ i ].showDuration -= dt;
				}
				VisualizePuppetInternal( i );
			}
		}
		else
		{
			timeToNextUpdate -= dt;
		}
	}

	public function ToggleShowWeaponsStreaming()
	{
		showWeaponsStreaming = !( showWeaponsStreaming );
	}

}

