class Speaker extends InteractiveDevice
{
	default m_controllerTypeName = 'SpeakerController';
	protected var m_soundEventPlaying : Bool;
	protected var m_soundEvent : CName;
	protected editable var m_effectRef : EffectRef;
	protected var m_deafGameEffect : EffectInstance;
	protected var m_targets : array< weak< ScriptedPuppet > >;
	protected var m_statusEffect : TweakDBID;

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

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

	protected event OnPersitentStateInitialized( evt : GameAttachedEvent )
	{
		super.OnPersitentStateInitialized( evt );
	}

	protected override function TurnOnDevice()
	{
		super.TurnOnDevice();
		PlayAllSounds();
		UpdateDeviceState();
	}

	protected override function TurnOffDevice()
	{
		super.TurnOffDevice();
		StopAllSounds();
		UpdateDeviceState();
	}

	protected override function StartGlitching( glitchState : EGlitchState, optional intensity : Float )
	{
		PlaySound( this, GetDevicePS().GetGlitchSFX() );
		if( GetDevicePS().UseOnlyGlitchSFX() )
		{
			AudioSwitch( this, 'radio_station', 'station_none', 'radio' );
		}
		else
		{
			AudioSwitch( this, 'radio_station', GetDevicePS().GetCurrentStation(), 'radio' );
		}
	}

	protected override function StopGlitching()
	{
		if( GetDevicePS().UseOnlyGlitchSFX() )
		{
			StopSound( this, GetDevicePS().GetGlitchSFX() );
		}
		AudioSwitch( this, 'radio_station', GetDevicePS().GetCurrentStation(), 'radio' );
		StopGameEffect();
	}

	protected event OnChangeMusicAction( evt : ChangeMusicAction )
	{
		var settings : MusicSettings;
		settings = evt.GetMusicSettings();
		StopAllSounds();
		if( ( ( PlayRadio )( settings ) ) )
		{
			m_soundEventPlaying = false;
			GetDevicePS().SetCurrentStation( settings.GetSoundName() );
		}
		else if( ( ( PlaySoundEvent )( settings ) ) )
		{
			m_soundEventPlaying = true;
			m_soundEvent = settings.GetSoundName();
		}
		if( GetDevicePS().IsON() )
		{
			PlayAllSounds();
			StartGameEffect( settings.GetStatusEffect() );
		}
	}

	protected function StopAllSounds()
	{
		if( m_soundEventPlaying )
		{
			StopSound( this, m_soundEvent );
		}
		else
		{
			AudioSwitch( this, 'radio_station', 'station_none', 'radio' );
		}
	}

	protected function PlayAllSounds()
	{
		if( m_soundEventPlaying )
		{
			PlaySound( this, m_soundEvent );
		}
		else
		{
			AudioSwitch( this, 'radio_station', GetDevicePS().GetCurrentStation(), 'radio' );
		}
	}

	protected function StartGameEffect( effect : ESoundStatusEffects )
	{
		var newStatusEffect : TweakDBID;
		var evt : DelayEvent;
		StopGameEffect();
		if( effect == ESoundStatusEffects.DEAFENED )
		{
			newStatusEffect = T"BaseStatusEffect.Deaf";
		}
		else if( effect == ESoundStatusEffects.SUPRESS_NOISE )
		{
			newStatusEffect = T"BaseStatusEffect.SuppressNoise";
		}
		m_statusEffect = newStatusEffect;
		if( TDBID.IsValid( m_statusEffect ) )
		{
			evt = new DelayEvent;
			GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, evt, 1.0 );
		}
	}

	protected event OnDelayEvent( evt : DelayEvent )
	{
		CreateGameEffect();
	}

	protected function CreateGameEffect()
	{
		m_deafGameEffect = GameInstance.GetGameEffectSystem( GetGame() ).CreateEffect( m_effectRef, this );
		EffectData.SetFloat( m_deafGameEffect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.radius, GetDevicePS().GetRange() );
		EffectData.SetVector( m_deafGameEffect.GetSharedData(), GetAllBlackboardDefs().EffectSharedData.position, GetAcousticQuerryStartPoint() );
		m_deafGameEffect.Run();
	}

	protected function StopGameEffect()
	{
		var i : Int32;
		if( TDBID.IsValid( m_statusEffect ) )
		{
			for( i = 0; i < m_targets.Size(); i += 1 )
			{
				RemoveStatusEffect( m_targets[ i ] );
			}
		}
		if( m_deafGameEffect )
		{
			m_deafGameEffect.Terminate();
			m_deafGameEffect = NULL;
		}
		m_targets.Clear();
	}

	protected event OnTargetAcquired( evt : TargetAcquiredEvent )
	{
		if( !( m_targets.Contains( evt.target ) ) )
		{
			m_targets.PushBack( evt.target );
		}
		ApplyStatusEffect( evt.target );
	}

	protected event OnTargetLost( evt : TargetLostEvent )
	{
		var i : Int32;
		i = m_targets.FindFirst( evt.target );
		if( i >= 0 )
		{
			m_targets.EraseFast( i );
		}
		RemoveStatusEffect( evt.target );
	}

	protected function ApplyStatusEffect( target : weak< GameObject > )
	{
		if( TDBID.IsValid( m_statusEffect ) )
		{
			StatusEffectHelper.ApplyStatusEffect( target, m_statusEffect, GetEntityID() );
		}
	}

	protected function RemoveStatusEffect( target : weak< GameObject > )
	{
		if( TDBID.IsValid( m_statusEffect ) )
		{
			StatusEffectHelper.RemoveStatusEffect( target, m_statusEffect );
		}
	}

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

	protected const override function GetController() : SpeakerController
	{
		return ( ( SpeakerController )( m_controller ) );
	}

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

}

