enum DoorProximityDetectorAppearanceStateType
{
	On = 0,
	Off = 1,
	Bars = 2,
	Green = 3,
	Alarm = 4,
	Glitch = 5,
}

class DoorProximityDetector extends ProximityDetector
{
	default m_controllerTypeName = 'DoorProximityDetectorController';
	private var m_triggeredAlarmID : DelayID;
	private var m_blinkInterval : Float;
	default m_blinkInterval = 2.0f;
	private var m_authorizationLevel : ESecurityAccessLevel;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		super.OnRequestComponents( ri );
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		super.OnTakeControl( ri );
		m_controller = ( ( DoorProximityDetectorController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected event OnGameAttached()
	{
		var secSys : SecuritySystemControllerPS;
		secSys = GetDevicePS().GetSecuritySystem();
		if( ( secSys && !( secSys.IsSystemSafe() ) ) && !( IsPlayerAuthorized() ) )
		{
			TriggerAlarmBehavior( true );
		}
	}

	protected event OnDetach()
	{
		TriggerAlarmBehavior( false );
	}

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

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

	protected override function TurnOffDevice()
	{
		super.TurnOffDevice();
		SetAppearanceState( DoorProximityDetectorAppearanceStateType.Off );
	}

	protected override function TurnOnDevice()
	{
		super.TurnOnDevice();
		LockDevice( true );
	}

	protected override function LockDevice( shouldLock : Bool )
	{
		if( shouldLock )
		{
			if( IsPlayerAuthorized() )
			{
				SetAppearanceState( DoorProximityDetectorAppearanceStateType.On );
			}
			else
			{
				SetAppearanceState( DoorProximityDetectorAppearanceStateType.Bars );
			}
		}
		else
		{
			SetAppearanceState( DoorProximityDetectorAppearanceStateType.Green );
		}
	}

	private function IsPlayerAuthorized() : Bool
	{
		GetDevicePS().IsConnectedToSecuritySystem( m_authorizationLevel );
		return GetDevicePS().GetSecuritySystem().IsUserAuthorized( GetPlayerMainObject().GetEntityID(), m_authorizationLevel );
	}

	private function SetAppearanceState( appearanceState : DoorProximityDetectorAppearanceStateType )
	{
		var meshName : CName;
		switch( appearanceState )
		{
			case DoorProximityDetectorAppearanceStateType.On:
			{
				meshName = 'on';
				break;
			}
			case DoorProximityDetectorAppearanceStateType.Off:
			{
				meshName = 'off';
				break;
			}
			case DoorProximityDetectorAppearanceStateType.Bars:
			{
				meshName = 'bars';
				break;
			}
			case DoorProximityDetectorAppearanceStateType.Green:
			{
				meshName = 'green';
				break;
			}
			case DoorProximityDetectorAppearanceStateType.Alarm:
			{
				meshName = 'alarm';
				break;
			}
			case DoorProximityDetectorAppearanceStateType.Glitch:
			{
				meshName = 'glitch';
				break;
			}
		}
		SetMeshAppearance( meshName );
	}

	private function TriggerAlarmBehavior( yes : Bool )
	{
		var ds : DelaySystem;
		var alarm : AlarmEvent;
		if( GetDevicePS().GetSecuritySystem().IsRestarting() )
		{
			LockDevice( false );
			return;
		}
		ds = GameInstance.GetDelaySystem( GetGame() );
		if( !( ds ) )
		{
			return;
		}
		if( yes )
		{
			if( !( IsAlarmTriggered() ) )
			{
				alarm = new AlarmEvent;
				m_triggeredAlarmID = ds.DelayEvent( this, alarm, m_blinkInterval );
			}
		}
		else if( IsAlarmTriggered() )
		{
			CancelAlarmCallback();
			LockDevice( !( GetDevicePS().GetSecuritySystem().IsRestarting() ) );
		}
	}

	protected event OnSecuritySystemOutput( evt : SecuritySystemOutput )
	{
		if( IsDeviceUsable() )
		{
			TriggerAlarmBehavior( evt.GetCachedSecurityState() == ESecuritySystemState.COMBAT );
		}
	}

	private function IsAlarmTriggered() : Bool
	{
		var nullID : DelayID;
		if( m_triggeredAlarmID == nullID )
		{
			return false;
		}
		return true;
	}

	protected event OnAlarmBlink( evt : AlarmEvent )
	{
		if( GetDevicePS().GetSecuritySystem().IsRestarting() || GetDevicePS().GetSecuritySystem().IsSystemSafe() )
		{
			CancelAlarmCallback();
			TriggerAlarmBehavior( false );
			LockDevice( true );
			return false;
		}
		if( evt.isValid )
		{
			SetAppearanceState( DoorProximityDetectorAppearanceStateType.Bars );
		}
		else
		{
			SetAppearanceState( DoorProximityDetectorAppearanceStateType.Alarm );
		}
		evt.isValid = !( evt.isValid );
		m_triggeredAlarmID = GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, evt, m_blinkInterval );
	}

	private function CancelAlarmCallback()
	{
		var ds : DelaySystem;
		var emptyID : DelayID;
		ds = GameInstance.GetDelaySystem( GetGame() );
		if( !( ds ) )
		{
			return;
		}
		ds.CancelCallback( m_triggeredAlarmID );
		ds.CancelDelay( m_triggeredAlarmID );
		m_triggeredAlarmID = emptyID;
	}

	protected override function StartGlitching( glitchState : EGlitchState, optional intensity : Float )
	{
		SetAppearanceState( DoorProximityDetectorAppearanceStateType.Glitch );
	}

	protected override function StopGlitching()
	{
		LockDevice( true );
	}

}

