class RetractableAd extends BaseAnimatedDevice
{
	default m_controllerTypeName = 'RetractableAdController';
	protected var m_offMeshConnection : OffMeshConnectionComponent;
	protected var m_areaComponent : TriggerComponent;
	protected var m_advUiComponent : IComponent;
	protected var m_isPartOfTheTrap : Bool;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		super.OnRequestComponents( ri );
		EntityRequestComponentsInterface.RequestComponent( ri, 'offMeshConnection', 'OffMeshConnectionComponent', false );
		EntityRequestComponentsInterface.RequestComponent( ri, 'ui', 'AdvertisementWidgetComponent', false );
		EntityRequestComponentsInterface.RequestComponent( ri, 'area', 'TriggerComponent', false );
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		super.OnTakeControl( ri );
		m_offMeshConnection = ( ( OffMeshConnectionComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'offMeshConnection' ) ) );
		m_advUiComponent = ( ( IComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'ui' ) ) );
		m_areaComponent = ( ( TriggerComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'area' ) ) );
		m_controller = ( ( RetractableAdController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected event OnActivateDevice( evt : ActivateDevice )
	{
		super.OnActivateDevice( evt );
		if( GetDevicePS().IsConnected() )
		{
			m_isPartOfTheTrap = true;
		}
	}

	protected override function ActivateAnimation()
	{
		var count : array< Entity >;
		count = GetEntitiesInArea();
		if( GetDevicePS().IsActive() && ( count.Size() > 0 ) )
		{
			ApplyImpulse( count );
		}
		super.ActivateAnimation();
	}

	protected override function OnPlayAnimation()
	{
		if( GetDevicePS().IsNotActive() )
		{
			m_gameplayRoleComponent.ToggleMappin( gamedataMappinVariant.HazardWarningVariant, false );
			ToggleOffMeshConnection( true );
			ToggleLights( false );
		}
		else
		{
			m_gameplayRoleComponent.ToggleMappin( gamedataMappinVariant.HazardWarningVariant, true, true );
			ToggleOffMeshConnection( false );
			ToggleLights( true );
		}
	}

	protected override function GetTimeScale() : Float
	{
		if( m_isPartOfTheTrap )
		{
			return 0.69999999;
		}
		return super.GetTimeScale();
	}

	protected function ToggleOffMeshConnection( toggle : Bool )
	{
		if( m_offMeshConnection )
		{
			if( toggle )
			{
				m_offMeshConnection.EnableOffMeshConnection();
				m_offMeshConnection.EnableForPlayer();
			}
			else
			{
				m_offMeshConnection.DisableOffMeshConnection();
				m_offMeshConnection.DisableForPlayer();
			}
		}
	}

	protected function ToggleLights( toggle : Bool )
	{
		var lightEvent : ToggleLightEvent;
		lightEvent = new ToggleLightEvent;
		lightEvent.toggle = toggle;
		QueueEvent( lightEvent );
	}

	protected event OnPhysicalDestructionEvent( evt : PhysicalDestructionEvent )
	{
		if( evt.componentName == 'destructible_glass' && ( evt.levelOfDestruction == 1 ) )
		{
			m_gameplayRoleComponent.ToggleMappin( gamedataMappinVariant.HazardWarningVariant, false );
			DisableTrap();
		}
		else
		{
			GetDevicePS().ForceDisableDevice();
		}
	}

	protected function DisableTrap()
	{
		var trap : RoadBlockTrapControllerPS;
		if( GetDevicePS().IsConnected() )
		{
			trap = GetDevicePS().GetTrapController();
			trap.ForceDisableDevice();
		}
	}

	public const function GetEntitiesInArea() : array< Entity >
	{
		return m_areaComponent.GetOverlappingEntities();
	}

	protected override function StartGlitching( glitchState : EGlitchState, optional intensity : Float )
	{
		var evt : AdvertGlitchEvent;
		evt = new AdvertGlitchEvent;
		evt.SetShouldGlitch( 1.0 );
		QueueEvent( evt );
		UpdateDeviceState();
	}

	protected override function StopGlitching()
	{
		var evt : AdvertGlitchEvent;
		evt = new AdvertGlitchEvent;
		evt.SetShouldGlitch( 0.0 );
		QueueEvent( evt );
	}

	private function ApplyImpulse( const activators : ref< array< Entity > > )
	{
		var ev : PSMImpulse;
		var i : Int32;
		var impulseInLocalSpace : Vector4;
		var devicePosition : Vector4;
		var activatorPosition : Vector4;
		var direction : Vector4;
		var deviceForward : Vector4;
		var impulsMultiplier : Float;
		if( m_isPartOfTheTrap )
		{
			return;
		}
		devicePosition = GetWorldPosition();
		deviceForward = GetWorldForward();
		impulsMultiplier = TDB.GetFloat( T"player.externalImpules.bilboard" );
		for( i = 0; i < activators.Size(); i += 1 )
		{
			ev = new PSMImpulse;
			ev.id = 'impulse';
			activatorPosition = activators[ i ].GetWorldPosition();
			direction = activatorPosition - devicePosition;
			if( Vector4.Dot( direction, deviceForward ) < 0.0 )
			{
				deviceForward = -( deviceForward );
			}
			impulseInLocalSpace = deviceForward * impulsMultiplier;
			ev.impulse = impulseInLocalSpace;
			activators[ i ].QueueEvent( ev );
		}
	}

	protected event OnAreaEnter( evt : AreaEnteredEvent )
	{
		var activator : weak< GameObject >;
		if( GetDevicePS().IsDisabled() || GetDevicePS().IsUnpowered() )
		{
			return false;
		}
		activator = ( ( GameObject )( EntityGameInterface.GetEntity( evt.activator ) ) );
		if( ( activator.IsPlayer() && GetDevicePS().IsActivated() ) && evt.componentName == 'areaTop' )
		{
			GameInstance.GetPersistencySystem( GetGame() ).QueuePSEvent( GetDevicePS().GetID(), GetDevicePS().GetClassName(), GetDevicePS().ActionDeactivateDevice() );
		}
	}

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

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

}

