enum ELightSequenceStage
{
	NONE = 0,
	INPROGRESS = 1,
	COMPLETE = 2,
}

class LightSwitchRequest extends Event
{
	var requestNumber : Int32;
}

struct TrafficPersistentData
{
	var m_invertTrafficEvents : Bool;
}

struct TrafficLightResaveData
{
	var m_transitionDuration : Float;
	var m_playNotificationSounds : Bool;
	var m_invertTrafficEvents : Bool;
}

class TrafficLight extends Device
{
	default m_controllerTypeName = 'TrafficLightController';
	protected var m_lightState : worldTrafficLightColor;
	protected var m_trafficLightMesh : PhysicalMeshComponent;
	protected var m_destroyedMesh : PhysicalMeshComponent;

	protected event OnRequestComponents( ri : EntityRequestComponentsInterface )
	{
		super.OnRequestComponents( ri );
		EntityRequestComponentsInterface.RequestComponent( ri, 'traffic_light_device', 'PhysicalMeshComponent', false );
		EntityRequestComponentsInterface.RequestComponent( ri, 'traffic_light_destroyed', 'PhysicalMeshComponent', false );
	}

	protected event OnTakeControl( ri : EntityResolveComponentsInterface )
	{
		super.OnTakeControl( ri );
		m_trafficLightMesh = ( ( PhysicalMeshComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'traffic_light_device' ) ) );
		m_destroyedMesh = ( ( PhysicalMeshComponent )( EntityResolveComponentsInterface.GetComponent( ri, 'traffic_light_destroyed' ) ) );
		m_controller = ( ( TrafficLightController )( EntityResolveComponentsInterface.GetComponent( ri, 'controller' ) ) );
	}

	protected override function ResolveGameplayState()
	{
		super.ResolveGameplayState();
		if( ( ( TrafficLightControllerPS )( GetDevicePS() ) ).IsMasterDestroyed() )
		{
			DeactivateDeviceSilent();
		}
		else
		{
			ActivateDevice();
		}
	}

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

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

	protected event OnTrafficLightChangeEvent( evt : TrafficLightChangeEvent )
	{
		if( m_lightState != evt.lightColor && GetDevicePS().IsInitialized() )
		{
			TurnOffLights();
			if( evt.lightColor == worldTrafficLightColor.YELLOW )
			{
				CommenceLightChangeSequence( m_lightState );
				m_lightState = evt.lightColor;
			}
			else
			{
				m_lightState = evt.lightColor;
				CompleteLightChangeSequence();
			}
		}
	}

	protected virtual function CommenceLightChangeSequence( color : worldTrafficLightColor )
	{
		if( color == worldTrafficLightColor.RED )
		{
			CommenceChangeToGreen();
		}
		else
		{
			CommenceChangeToRed();
		}
	}

	protected virtual function CommenceChangeToRed()
	{
		HandleYellowLight( true );
	}

	protected virtual function CommenceChangeToGreen()
	{
		HandleRedLight( true );
		HandleYellowLight( true );
	}

	protected virtual function CompleteLightChangeSequence()
	{
		if( m_lightState == worldTrafficLightColor.RED )
		{
			HandleRedLight( true );
		}
		else
		{
			HandleGreenLight( true );
		}
	}

	protected event OnMasterDeviceDestroyed( evt : MasterDeviceDestroyed )
	{
		var meshInterface : PhysicalBodyInterface;
		var delayEvent : DelayEvent;
		meshInterface = m_destroyedMesh.CreatePhysicalBodyInterface();
		meshInterface.ToggleKinematic( true );
		meshInterface.AddLinearImpulse( Vector4( 0.0, 0.5, 0.0, 0.0 ), true );
		delayEvent = new DelayEvent;
		GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, delayEvent, RandRangeF( 5.0, 10.0 ) );
	}

	protected event OnDelayEvent( evt : DelayEvent )
	{
		m_destroyedMesh.Toggle( false );
	}

	protected override function TurnOnDevice()
	{
		DetermineLightsFixedState();
	}

	protected override function TurnOffDevice()
	{
		TurnOffLights();
	}

	protected override function DeactivateDevice()
	{
		TurnOffLights();
		GetDevicePS().GetDeviceOperationsContainer().Execute( 'death_VFX', this );
		m_trafficLightMesh.Toggle( false );
		m_destroyedMesh.Toggle( true );
	}

	protected function DeactivateDeviceSilent()
	{
		TurnOffLights();
		m_trafficLightMesh.Toggle( false );
	}

	protected override function ActivateDevice()
	{
		if( GetDevicePS().IsON() )
		{
			DetermineLightsFixedState();
		}
		if( m_trafficLightMesh )
		{
			m_trafficLightMesh.Toggle( true );
		}
		if( m_destroyedMesh )
		{
			m_destroyedMesh.Toggle( false );
		}
	}

	protected function HandleRedLight( enable : Bool )
	{
		var toggleEvent : ToggleLightByNameEvent;
		toggleEvent = new ToggleLightByNameEvent;
		toggleEvent.toggle = enable;
		toggleEvent.componentName = 'red';
		QueueEvent( toggleEvent );
	}

	protected virtual function HandleYellowLight( enable : Bool )
	{
		var toggleEvent : ToggleLightByNameEvent;
		toggleEvent = new ToggleLightByNameEvent;
		toggleEvent.toggle = enable;
		toggleEvent.componentName = 'yellow';
		QueueEvent( toggleEvent );
	}

	protected virtual function HandleGreenLight( enable : Bool )
	{
		var toggleEvent : ToggleLightByNameEvent;
		toggleEvent = new ToggleLightByNameEvent;
		toggleEvent.toggle = enable;
		toggleEvent.componentName = 'green';
		QueueEvent( toggleEvent );
	}

	protected function TurnOffLights()
	{
		var evt : ToggleLightEvent;
		evt = new ToggleLightEvent;
		evt.toggle = false;
		QueueEvent( evt );
	}

	protected virtual function DetermineLightsFixedState()
	{
		TurnOffLights();
		if( !( GetDevicePS().IsON() ) )
		{
			return;
		}
		if( m_lightState == worldTrafficLightColor.RED )
		{
			HandleRedLight( true );
		}
		else
		{
			HandleGreenLight( true );
		}
	}

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

}

