class RoadBlock extends InteractiveDevice
{
	default m_controllerTypeName = 'RoadBlockController';
	[ category = "AnimationSetup" ]
	instanceeditable var m_openingSpeed : Float;
	default m_openingSpeed = 2.0f;
	private const instanceeditable var m_coverObjectRefs : array< NodeRef >;
	protected var m_animationController : AnimationControllerComponent;
	protected var m_offMeshConnection : OffMeshConnectionComponent;
	private var m_animFeature : AnimFeature_RoadBlock;
	protected editable var m_animationType : EAnimationType;
	protected var m_forceEnableLink : Bool;
	private var m_globalCoverObjectRefs : array< GlobalNodeRef >;
	private var m_areGlobalCoverRefsInitialized : Bool;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		super.OnRequestComponents( ri );
		EntityRequestComponentsInterface.RequestComponent( ri, 'animController', 'AnimationControllerComponent', false );
		EntityRequestComponentsInterface.RequestComponent( ri, 'offMeshConnection', 'OffMeshConnectionComponent', false );
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		super.OnTakeControl( ri );
		m_animationController = ( ( AnimationControllerComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'animController' ) ) );
		m_offMeshConnection = ( ( OffMeshConnectionComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'offMeshConnection' ) ) );
		if( !( m_animationController ) )
		{
		}
		if( !( m_offMeshConnection ) )
		{
		}
		m_controller = ( ( RoadBlockController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected override function ResolveGameplayState()
	{
		super.ResolveGameplayState();
		m_animFeature = new AnimFeature_RoadBlock;
		m_animFeature.initOpen = ( ( RoadBlockControllerPS )( GetDevicePS() ) ).IsBlocking() ^ ( ( RoadBlockControllerPS )( GetDevicePS() ) ).NegateAnim();
		UpdateRoadBlockStateImmediate();
	}

	protected event OnGameAttached()
	{
		TryInitializeGlobalCoverObjectRefs();
		RegisterCoverObjects();
		super.OnGameAttached();
	}

	private function TryInitializeGlobalCoverObjectRefs()
	{
		var i : Int32;
		if( !( m_areGlobalCoverRefsInitialized ) )
		{
			for( i = 0; i < m_coverObjectRefs.Size(); i += 1 )
			{
				m_globalCoverObjectRefs.PushBack( ResolveNodeRefWithEntityID( m_coverObjectRefs[ i ], GetEntityID() ) );
			}
			m_areGlobalCoverRefsInitialized = true;
		}
	}

	private function RegisterCoverObjects()
	{
		var i : Int32;
		var coverManager : CoverManager;
		coverManager = GameInstance.GetCoverManager( GetGame() );
		for( i = 0; i < m_globalCoverObjectRefs.Size(); i += 1 )
		{
			coverManager.RegisterCoverPreInstanceData( m_globalCoverObjectRefs[ i ], GetDevicePS().IsBlocking() );
		}
	}

	protected event OnDetach()
	{
		UnregisterCoverObjects();
		super.OnDetach();
	}

	private function UnregisterCoverObjects()
	{
		var i : Int32;
		var coverManager : CoverManager;
		coverManager = GameInstance.GetCoverManager( GetGame() );
		for( i = 0; i < m_globalCoverObjectRefs.Size(); i += 1 )
		{
			coverManager.UnregisterCoverPreInstanceData( m_globalCoverObjectRefs[ i ] );
		}
	}

	private const override function GetController() : RoadBlockController
	{
		return ( ( RoadBlockController )( m_controller ) );
	}

	public const override function GetDevicePS() : RoadBlockControllerPS
	{
		return GetController().GetPS();
	}

	protected event OnToggleBlockade( evt : ToggleBlockade )
	{
		UpdateRoadBlockState();
		UpdateDeviceState();
	}

	protected event OnQuickHackToggleBlockade( evt : QuickHackToggleBlockade )
	{
		UpdateRoadBlockState();
		UpdateDeviceState();
	}

	protected event OnQuestForceRoadBlockadeActivate( evt : QuestForceRoadBlockadeActivate )
	{
		UpdateRoadBlockState();
		UpdateDeviceState();
	}

	protected event OnQuestForceRoadBlockadeDeactivate( evt : QuestForceRoadBlockadeDeactivate )
	{
		UpdateRoadBlockState();
		UpdateDeviceState();
	}

	protected event OnActivateDevice( evt : ActivateDevice )
	{
		UpdateRoadBlockState();
	}

	protected event OnDeactivateDevice( evt : DeactivateDevice )
	{
		UpdateRoadBlockState();
	}

	protected event OnPhysicalDestructionEvent( evt : PhysicalDestructionEvent )
	{
		ToggleOffMeshConnection( true );
		m_forceEnableLink = true;
	}

	protected override function DeactivateDevice()
	{
		super.DeactivateDevice();
		m_animationController.Toggle( false );
	}

	protected override function ActivateDevice()
	{
		super.ActivateDevice();
		if( m_animationController )
		{
			m_animationController.Toggle( true );
		}
	}

	private function UpdateRoadBlockState()
	{
		InternalUpdateRoadBlockState( false );
	}

	private function UpdateRoadBlockStateImmediate()
	{
		InternalUpdateRoadBlockState( true );
	}

	private function InternalUpdateRoadBlockState( immediate : Bool )
	{
		UpdateAnimationState( immediate );
		ToggleOffMeshConnection( !( GetDevicePS().IsBlocking() ) );
		UpdateCoverObjectState();
	}

	private function UpdateCoverObjectState()
	{
		if( GetDevicePS().IsBlocking() )
		{
			EnableCoverObjects();
		}
		else
		{
			DisableCoverObjects();
		}
	}

	private function EnableCoverObjects()
	{
		var i : Int32;
		var coverManager : CoverManager;
		coverManager = GameInstance.GetCoverManager( GetGame() );
		for( i = 0; i < m_globalCoverObjectRefs.Size(); i += 1 )
		{
			coverManager.SetCoverEnabled( m_globalCoverObjectRefs[ i ] );
		}
	}

	private function DisableCoverObjects()
	{
		var i : Int32;
		var coverManager : CoverManager;
		coverManager = GameInstance.GetCoverManager( GetGame() );
		for( i = 0; i < m_globalCoverObjectRefs.Size(); i += 1 )
		{
			coverManager.SetCoverDisabled( m_globalCoverObjectRefs[ i ] );
		}
	}

	private function UpdateAnimationState( immediate : Bool )
	{
		if( m_animationType == EAnimationType.REGULAR )
		{
			Animate( immediate );
		}
		else if( m_animationType == EAnimationType.TRANSFORM )
		{
			TransformAnimate( immediate );
		}
	}

	private function Animate( immediate : Bool )
	{
		m_animFeature.duration = m_openingSpeed;
		m_animFeature.isOpening = GetDevicePS().IsBlocking() ^ GetDevicePS().NegateAnim();
		if( immediate )
		{
			m_animFeature.duration /= 1000.0;
		}
		AnimationControllerComponent.ApplyFeature( this, 'Road_block', m_animFeature );
	}

	private function TransformAnimate( immediate : Bool )
	{
		var playEvent : gameTransformAnimationPlayEvent;
		var skipEvent : gameTransformAnimationSkipEvent;
		playEvent = new gameTransformAnimationPlayEvent;
		playEvent.looping = false;
		playEvent.timesPlayed = 1;
		playEvent.timeScale = 1.0;
		if( GetDevicePS().IsNotBlocking() )
		{
			playEvent.animationName = 'closing';
		}
		else
		{
			playEvent.animationName = 'opening';
		}
		QueueEvent( playEvent );
		if( immediate )
		{
			skipEvent = new gameTransformAnimationSkipEvent;
			skipEvent.skipToEnd = true;
			skipEvent.animationName = playEvent.animationName;
			QueueEvent( skipEvent );
		}
	}

	private function ToggleOffMeshConnection( toggle : Bool )
	{
		if( m_offMeshConnection && !( m_forceEnableLink ) )
		{
			if( toggle )
			{
				m_offMeshConnection.EnableOffMeshConnection();
				m_offMeshConnection.EnableForPlayer();
			}
			else
			{
				m_offMeshConnection.DisableOffMeshConnection();
				m_offMeshConnection.DisableForPlayer();
			}
		}
	}

	public const override function DeterminGameplayRole() : EGameplayRole
	{
		return EGameplayRole.ClearPath;
	}

}

