enum ESoundStatusEffects
{
	NONE = 0,
	DEAFENED = 1,
	SUPRESS_NOISE = 2,
}

class SoundSystemController extends MasterController
{

	public const override function GetPS() : SoundSystemControllerPS
	{
		return ( ( SoundSystemControllerPS )( GetBasePS() ) );
	}

}

class SoundSystemControllerPS extends MasterControllerPS
{
	protected instanceeditable var m_defaultAction : Int32;
	protected const instanceeditable var m_soundSystemSettings : array< SoundSystemSettings >;
	protected var m_currentEvent : ChangeMusicAction;
	protected var m_cachedEvent : ChangeMusicAction;

	protected event OnInstantiated()
	{
		super.OnInstantiated();
		if( !( IsStringValid( m_deviceName ) ) )
		{
			m_deviceName = "Gameplay-Devices-DisplayNames-Switch";
		}
	}

	protected override function Initialize()
	{
		super.Initialize();
	}

	protected override function GameAttached()
	{
		if( m_defaultAction >= m_soundSystemSettings.Size() )
		{
			m_defaultAction = 0;
		}
		if( m_soundSystemSettings.Size() > 0 )
		{
			m_currentEvent = ActionChangeMusic( m_soundSystemSettings[ m_defaultAction ] );
			RefreshSlaves_Event();
		}
	}

	public override function GetActions( out actions : array< DeviceAction >, context : GetActionsContext ) : Bool
	{
		var i : Int32;
		super.GetActions( actions, context );
		for( i = 0; i < m_soundSystemSettings.Size(); i += 1 )
		{
			if( IsON() && context.requestType == gamedeviceRequestType.External )
			{
				actions.PushBack( ActionChangeMusic( m_soundSystemSettings[ i ] ) );
			}
		}
		SetActionIllegality( actions, m_illegalActions.regularActions );
		return true;
	}

	protected const override function CanCreateAnyQuickHackActions() : Bool
	{
		var i : Int32;
		for( i = 0; i < m_soundSystemSettings.Size(); i += 1 )
		{
			if( m_soundSystemSettings[ i ].m_canBeUsedAsQuickHack )
			{
				return true;
			}
		}
		return false;
	}

	protected override function GetQuickHackActions( out outActions : array< DeviceAction >, const context : ref< GetActionsContext > )
	{
		var i : Int32;
		var currentAction : ScriptableDeviceAction;
		for( i = 0; i < m_soundSystemSettings.Size(); i += 1 )
		{
			if( m_soundSystemSettings[ i ].m_canBeUsedAsQuickHack )
			{
				currentAction = ActionChangeMusic( m_soundSystemSettings[ i ] );
				currentAction.SetObjectActionID( T"DeviceAction.MalfunctionClassHack" );
				outActions.PushBack( currentAction );
			}
		}
		FinalizeGetQuickHackActions( outActions, context );
	}

	public override function GetQuickHackActionsExternal( out outActions : array< DeviceAction >, const context : ref< GetActionsContext > )
	{
		GetQuickHackActions( outActions, context );
	}

	protected function ActionChangeMusic( settings : SoundSystemSettings ) : ChangeMusicAction
	{
		var action : ChangeMusicAction;
		action = new ChangeMusicAction;
		action.SetUp( this );
		action.SetProperties( settings.m_musicSettings, settings.m_interactionName );
		action.AddDeviceName( m_deviceName );
		action.CreateActionWidgetPackage();
		if( settings.m_canBeUsedAsQuickHack )
		{
			action.SetInteractionIcon( T"ChoiceCaptionParts.DistractIcon" );
			action.CreateInteraction( , , settings.m_interactionName );
		}
		return action;
	}

	public function OnChangeMusicAction( evt : ChangeMusicAction ) : EntityNotificationType
	{
		m_currentEvent = evt;
		EvaluateQuickHacksAvailability( evt.m_settings );
		RefreshSlaves_Event();
		UseNotifier( evt );
		NotifyParents_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function EvaluateQuickHacksAvailability( settings : MusicSettings )
	{
		var i : Int32;
		for( i = 0; i < m_soundSystemSettings.Size(); i += 1 )
		{
			if( m_soundSystemSettings[ i ].m_musicSettings == settings )
			{
				m_soundSystemSettings[ i ].m_canBeUsedAsQuickHack = false;
			}
		}
	}

	protected export override function OnRefreshSlavesEvent( evt : RefreshSlavesEvent ) : EntityNotificationType
	{
		if( IsON() )
		{
			RefreshSlaves();
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function RefreshSlaves()
	{
		var i : Int32;
		var devices : array< DeviceComponentPS >;
		devices = GetImmediateSlaves();
		for( i = 0; i < devices.Size(); i += 1 )
		{
			if( ( ( SpeakerControllerPS )( devices[ i ] ) ) )
			{
				ExecutePSAction( m_currentEvent, devices[ i ] );
			}
		}
	}

	protected function OnRefreshSlavesState( evt : RefreshSlavesState ) : EntityNotificationType
	{
		RefreshSlavesState();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function RefreshSlavesState()
	{
		var i : Int32;
		var devices : array< DeviceComponentPS >;
		devices = GetImmediateSlaves();
		for( i = 0; i < devices.Size(); i += 1 )
		{
			if( ( ( SpeakerControllerPS )( devices[ i ] ) ) )
			{
				if( IsON() )
				{
					ExecutePSAction( ActionSetDeviceON(), devices[ i ] );
				}
				else
				{
					ExecutePSAction( ActionSetDeviceOFF(), devices[ i ] );
				}
			}
		}
	}

	protected override function OnSetDeviceON( evt : SetDeviceON ) : EntityNotificationType
	{
		super.OnSetDeviceON( evt );
		RefreshSlavesState_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	protected override function OnSetDeviceOFF( evt : SetDeviceOFF ) : EntityNotificationType
	{
		super.OnSetDeviceOFF( evt );
		RefreshSlavesState_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	protected override function OnQuestForceOFF( evt : QuestForceOFF ) : EntityNotificationType
	{
		super.OnQuestForceOFF( evt );
		RefreshSlavesState_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	protected override function OnQuestForceON( evt : QuestForceON ) : EntityNotificationType
	{
		super.OnQuestForceON( evt );
		RefreshSlavesState_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public override function OnToggleON( evt : ToggleON ) : EntityNotificationType
	{
		super.OnToggleON( evt );
		RefreshSlavesState_Event();
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public function RefreshSlavesState_Event()
	{
		var evt : RefreshSlavesState;
		evt = new RefreshSlavesState;
		GetPersistencySystem().QueuePSEvent( GetID(), GetClassName(), evt );
	}

	protected override function GetDeviceIconTweakDBID() : TweakDBID
	{
		return T"DeviceIcons.RadioDeviceIcon";
	}

	protected override function GetBackgroundTextureTweakDBID() : TweakDBID
	{
		return T"DeviceIcons.RadioDeviceBackground";
	}

}

struct SoundSystemSettings
{
	[ customEditor = "TweakDBGroupInheritance;Interactions.InteractionChoice;Interactions.MountChoice" ]
	instanceeditable var m_interactionName : TweakDBID;
	instanceeditable inlined var m_musicSettings : MusicSettings;
	instanceeditable var m_canBeUsedAsQuickHack : Bool;
}

abstract class MusicSettings extends IScriptable
{
	protected instanceeditable var m_statusEffect : ESoundStatusEffects;

	public virtual function GetSoundName() : CName
	{
		return 'station_none';
	}

	public function GetStatusEffect() : ESoundStatusEffects
	{
		return m_statusEffect;
	}

	public function SetStatusEffect( effect : ESoundStatusEffects )
	{
		m_statusEffect = effect;
	}

}

class PlayRadio extends MusicSettings
{
	protected instanceeditable var m_radioStation : ERadioStationList;

	public function SetSoundName( soundname : ERadioStationList )
	{
		m_radioStation = soundname;
	}

	public function GetStation() : ERadioStationList
	{
		return m_radioStation;
	}

	public override function GetSoundName() : CName
	{
		return RadioStationDataProvider.GetStationName( GetStation() );
	}

}

class PlaySoundEvent extends MusicSettings
{
	[ customEditor = "AudioEvent" ]
	protected instanceeditable var soundEvent : CName;

	public override function GetSoundName() : CName
	{
		return soundEvent;
	}

	public function SetSoundName( soundname : CName )
	{
		soundEvent = soundname;
	}

}

class RefreshSlavesState extends Event
{
}

