class MovableDevice extends InteractiveDevice
{
	default m_controllerTypeName = 'MovableDeviceController';
	var m_workspotSideName : CName;
	protected const editable var m_sideTriggerNames : array< CName >;
	protected var m_triggerComponents : array< TriggerComponent >;
	protected const editable var m_offMeshConnectionsToOpenNames : array< CName >;
	protected var m_offMeshConnectionsToOpen : array< OffMeshConnectionComponent >;
	protected var m_additionalMeshComponent : MeshComponent;
	[ tooltip = "If set to true, the position of the WorkspotResourceComponent containing the player workspot will be used for the player during sync animations." ]
	protected editable var m_UseWorkspotComponentPosition : Bool;
	protected instanceeditable var m_shouldMoveRight : Bool;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		var i : Int32;
		super.OnRequestComponents( ri );
		EntityRequestComponentsInterface.RequestComponent( ri, 'additionalMesh', 'MeshComponent', false );
		for( i = 0; i < m_sideTriggerNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_sideTriggerNames[ i ], 'TriggerComponent', true );
		}
		for( i = 0; i < m_offMeshConnectionsToOpenNames.Size(); i += 1 )
		{
			EntityRequestComponentsInterface.RequestComponent( ri, m_offMeshConnectionsToOpenNames[ i ], 'OffMeshConnectionComponent', true );
		}
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		var i : Int32;
		super.OnTakeControl( ri );
		m_additionalMeshComponent = ( ( MeshComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'additionalMesh' ) ) );
		for( i = 0; i < m_sideTriggerNames.Size(); i += 1 )
		{
			m_triggerComponents.PushBack( ( ( TriggerComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_sideTriggerNames[ i ] ) ) ) );
		}
		for( i = 0; i < m_offMeshConnectionsToOpenNames.Size(); i += 1 )
		{
			m_offMeshConnectionsToOpen.PushBack( ( ( OffMeshConnectionComponent )( EntityResolveComponentsInterface.GetComponent( ri, m_offMeshConnectionsToOpenNames[ i ] ) ) ) );
		}
		m_controller = ( ( MovableDeviceController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected override function ResolveGameplayState()
	{
		super.ResolveGameplayState();
		UpdateOffMeshLinks();
	}

	protected event OnGameAttached()
	{
		super.OnGameAttached();
		UpdateAnimState();
	}

	protected override function EnterWorkspot( activator : GameObject, optional freeCamera : Bool, optional componentName : CName, optional syncSlotName : CName )
	{
		var workspotSystem : WorkspotGameSystem;
		var sideSuffix : CName;
		var workspotSlidingBehaviour : WorkspotSlidingBehaviour;
		workspotSystem = GameInstance.GetWorkspotSystem( activator.GetGame() );
		if( m_shouldMoveRight )
		{
			sideSuffix = m_workspotSideName + 'Right';
		}
		else
		{
			sideSuffix = m_workspotSideName + 'Left';
		}
		if( m_UseWorkspotComponentPosition )
		{
			workspotSlidingBehaviour = WorkspotSlidingBehaviour.PlayAtResourcePosition;
		}
		else
		{
			workspotSlidingBehaviour = WorkspotSlidingBehaviour.DontPlayAtResourcePosition;
		}
		workspotSystem.PlayInDevice( this, activator, 'lockedCamera', componentName + sideSuffix, 'deviceWorkspot' + sideSuffix, 'movableSync', 0.5, workspotSlidingBehaviour );
	}

	protected event OnActionDemolition( evt : ActionDemolition )
	{
		if( !( evt.IsCompleted() ) )
		{
			return false;
		}
		HandleMoveDevice();
	}

	protected event OnActionMoveObstacle( evt : MoveObstacle )
	{
		HandleMoveDevice();
	}

	protected function HandleMoveDevice()
	{
		var playerStateMachineBlackboard : IBlackboard;
		var player : GameObject;
		player = GameInstance.GetPlayerSystem( GetGame() ).GetLocalPlayerControlledGameObject();
		PlayTransformAnim();
		CheckCurrentSide();
		EnterWorkspot( player, false, 'playerWorkspot' );
		playerStateMachineBlackboard = GameInstance.GetBlackboardSystem( GetGame() ).GetLocalInstanced( player.GetEntityID(), GetAllBlackboardDefs().PlayerStateMachine );
		playerStateMachineBlackboard.SetBool( GetAllBlackboardDefs().PlayerStateMachine.IsInteractingWithDevice, true );
		UpdateAnimState();
		UpdateOffMeshLinks();
	}

	protected function PlayTransformAnim()
	{
		var playEvent : gameTransformAnimationPlayEvent;
		playEvent = new gameTransformAnimationPlayEvent;
		playEvent.animationName = 'start';
		playEvent.looping = false;
		playEvent.timesPlayed = 1;
		playEvent.timeScale = 1.0;
		QueueEvent( playEvent );
	}

	private function UpdateAnimState()
	{
		var animFeature : AnimFeature_SimpleDevice;
		animFeature = new AnimFeature_SimpleDevice;
		if( ( ( MovableDeviceControllerPS )( GetDevicePS() ) ).WasDeviceMoved() )
		{
			animFeature.isOpen = true;
			if( m_shouldMoveRight )
			{
				animFeature.isOpenRight = true;
			}
			else
			{
				animFeature.isOpenLeft = true;
			}
			AnimationControllerComponent.ApplyFeature( this, 'MovableDevice', animFeature );
			SetGameplayRoleToNone();
		}
	}

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

	protected function UpdateOffMeshLinks()
	{
		var i : Int32;
		if( ( ( MovableDeviceControllerPS )( GetDevicePS() ) ).WasDeviceMoved() )
		{
			for( i = 0; i < m_offMeshConnectionsToOpen.Size(); i += 1 )
			{
				m_offMeshConnectionsToOpen[ i ].EnableOffMeshConnection();
				m_offMeshConnectionsToOpen[ i ].EnableForPlayer();
			}
		}
		else
		{
			for( i = 0; i < m_offMeshConnectionsToOpen.Size(); i += 1 )
			{
				m_offMeshConnectionsToOpen[ i ].DisableOffMeshConnection();
				m_offMeshConnectionsToOpen[ i ].DisableForPlayer();
			}
		}
	}

	protected function CheckCurrentSide()
	{
		var finalName : String;
		var i : Int32;
		var j : Int32;
		var overlappingEntities : array< Entity >;
		for( i = 0; i < m_triggerComponents.Size(); i += 1 )
		{
			overlappingEntities = m_triggerComponents[ i ].GetOverlappingEntities();
			for( j = 0; j < overlappingEntities.Size(); j += 1 )
			{
				if( ( ( GameObject )( overlappingEntities[ j ] ) ).IsPlayer() )
				{
					finalName = "Side" + ( ( String )( ( i + 1 ) ) );
					m_workspotSideName = StringToName( finalName );
				}
			}
		}
		if( m_workspotSideName == '' )
		{
			m_workspotSideName = 'Side1';
		}
	}

}

class MovableQuestTrigger extends GameObject
{
	protected instanceeditable var m_factName : CName;
	protected instanceeditable var m_onlyDetectsPlayer : Bool;

	protected event OnAreaEnter( trigger : AreaEnteredEvent )
	{
		if( m_onlyDetectsPlayer )
		{
			if( ( ( GameObject )( EntityGameInterface.GetEntity( trigger.activator ) ) ).IsPlayer() )
			{
				SetFactValue( GetGame(), m_factName, 1 );
			}
		}
		else
		{
			SetFactValue( GetGame(), m_factName, 1 );
		}
	}

	protected event OnAreaExit( trigger : AreaExitedEvent )
	{
		if( m_onlyDetectsPlayer )
		{
			if( ( ( GameObject )( EntityGameInterface.GetEntity( trigger.activator ) ) ).IsPlayer() )
			{
				SetFactValue( GetGame(), m_factName, 0 );
			}
		}
		else
		{
			SetFactValue( GetGame(), m_factName, 0 );
		}
	}

}

