class BunkerDoor extends Door
{
	[ category = "Malfunction Sounds" ][ customEditor = "AudioEvent" ]
	private instanceeditable var m_loudAnnouncementOpenSoundName : CName;
	[ category = "Malfunction Sounds" ][ customEditor = "AudioEvent" ]
	private instanceeditable var m_halfOpenSoundName : CName;
	[ category = "Malfunction Sounds" ][ customEditor = "AudioEvent" ]
	private instanceeditable var m_glitchingSoundName : CName;
	[ customEditor = "AudioEvent" ]
	private instanceeditable var m_fastOpenSoundName : CName;

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

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

	protected override function ResolveGameplayState()
	{
		super.ResolveGameplayState();
		InitAnimation();
	}

	protected override function GetOpeningSpeed() : Float
	{
		if( IsInteractedByNPC() )
		{
			return GetDevicePS().GetNpcOpenSpeed();
		}
		return super.GetOpeningSpeed();
	}

	protected override function GetOpeningTime() : Float
	{
		if( IsInteractedByNPC() )
		{
			return GetDevicePS().GetNpcOpenTime();
		}
		return GetDevicePS().GetOpeningTime();
	}

	private function IsInteractedByNPC() : Bool
	{
		return m_whoOpened && !( m_whoOpened.IsPlayer() );
	}

	protected event OnSetDoorMalfunctioningType( evt : SetDoorMalfunctioningType )
	{
		GetDevicePS().SetMalfunctioningType( evt.malfunctioningType );
		StopSound( this, m_glitchingSoundName );
		InitAnimation( true );
	}

	private export function InitAnimation( optional reset : Bool )
	{
		if( GetDevicePS().IsMalfunctioningBehaviourActive( EMalfunctioningType.GLITCHING ) )
		{
			PlayGlitchingAnimation();
		}
		else if( reset )
		{
			StopSound( this, m_glitchingSoundName );
			ResetAnimation();
		}
	}

	private function PlayGlitchingAnimation()
	{
		PlaySound( this, m_glitchingSoundName );
		SetUpAnimation();
		m_animFeatureDoor.m_malfunctioning = ( ( Int32 )( EMalfunctioningType.GLITCHING ) );
		DisableOccluder();
		AnimationControllerComponent.ApplyFeature( this, 'door', m_animFeatureDoor );
	}

	private function ResetAnimation()
	{
		SetUpAnimation();
		AnimationControllerComponent.ApplyFeature( this, 'door', m_animFeatureDoor );
	}

	private function SetUpAnimation()
	{
		if( !( m_animFeatureDoor ) )
		{
			m_animFeatureDoor = new AnimFeatureDoor;
		}
		m_animFeatureDoor.m_openingSpeed = 1.0;
		m_animFeatureDoor.m_openingType = ( ( Int32 )( m_doorOpeningType ) );
		m_animFeatureDoor.m_doorSide = m_lastDoorSide;
		m_animFeatureDoor.m_malfunctioning = ( ( Int32 )( EMalfunctioningType.NONE ) );
	}

	private function PlayHalfOpenAnimation()
	{
		PlaySound( this, m_halfOpenSoundName );
		SetUpAnimation();
		m_animFeatureDoor.m_progress = 0.0;
		m_animFeatureDoor.m_malfunctioning = ( ( Int32 )( EMalfunctioningType.HALF_OPENING ) );
		AnimationControllerComponent.ApplyFeature( this, 'door', m_animFeatureDoor );
	}

	protected override function TriggerMoveDoorStimBroadcaster( broadcaster : StimBroadcasterComponent, reactionData : stimInvestigateData )
	{
		if( broadcaster )
		{
			if( GetDevicePS().IsMalfunctioningBehaviourActive( EMalfunctioningType.LOUD_ANNOUNCEMENT ) )
			{
				broadcaster.TriggerSingleBroadcast( this, gamedataStimType.OpeningDoor, GetDevicePS().GetMalfunctioningStimRange(), reactionData );
			}
			else
			{
				super.TriggerMoveDoorStimBroadcaster( broadcaster, reactionData );
			}
		}
	}

	private function PlayMalfunctionHalfOpen()
	{
		var ps : BunkerDoorControllerPS;
		ps = GetDevicePS();
		PlayHalfOpenAnimation();
		InvokePsBusyState( ps.GetOpeningTime() );
		MakeDoorToBeForceOpen( ps.GetOpeningTime() );
		BroadCastOpeningStim( ps.GetMalfunctioningStimRange() );
		ps.SetMalfunctioningType( EMalfunctioningType.NONE );
		DisableOccluder();
		EnableOccluderWithDelay( ps.GetOpeningTime() );
		EnablePlayerBlocker();
		UpdateDeviceState();
	}

	private function InvokePsBusyState( time : Float )
	{
		var ps : DoorControllerPS;
		var deviceBusy : SetBusyEvent;
		ps = GetDevicePS();
		deviceBusy = new SetBusyEvent;
		ps.SetIsBusy( true );
		GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, deviceBusy, time );
	}

	private function MakeDoorToBeForceOpen( delay : Float )
	{
		var skillCheck : SetSkillcheckEvent;
		var engDemoContainer : EngDemoContainer;
		var demolitionCheck : DemolitionSkillCheck;
		skillCheck = new SetSkillcheckEvent;
		engDemoContainer = new EngDemoContainer;
		demolitionCheck = new DemolitionSkillCheck;
		demolitionCheck.SetDifficulty( EGameplayChallengeLevel.TRIVIAL );
		demolitionCheck.SetIsActive( true );
		engDemoContainer.m_demolitionCheck = demolitionCheck;
		skillCheck.skillcheckContainer = engDemoContainer;
		GameInstance.GetDelaySystem( GetGame() ).DelayEvent( this, skillCheck, delay );
	}

	private function BroadCastOpeningStim( range : Float )
	{
		var broadcaster : StimBroadcasterComponent;
		var reactionData : stimInvestigateData;
		if( m_whoOpened && m_whoOpened.IsPlayer() )
		{
			broadcaster = GetStimBroadcasterComponent();
			if( broadcaster )
			{
				broadcaster.TriggerSingleBroadcast( this, gamedataStimType.OpeningDoor, range, reactionData );
			}
		}
	}

	protected event OnMalfunctionHalfOpen( evt : MalfunctionHalfOpen )
	{
		PlayMalfunctionHalfOpen();
	}

	protected override function PlayOpenDoorSound()
	{
		if( IsInteractedByNPC() )
		{
			PlaySound( this, m_fastOpenSoundName );
		}
		else if( GetDevicePS().IsMalfunctioningBehaviourActive( EMalfunctioningType.LOUD_ANNOUNCEMENT ) )
		{
			PlaySound( this, m_loudAnnouncementOpenSoundName );
		}
		else
		{
			super.PlayOpenDoorSound();
		}
	}

	protected override function SetupOpenDoorAnimationFeatures()
	{
		super.SetupOpenDoorAnimationFeatures();
		if( ( m_whoOpened && m_whoOpened.IsPlayer() ) && GetDevicePS().IsMalfunctioningBehaviourActive( EMalfunctioningType.LOUD_ANNOUNCEMENT ) )
		{
			m_animFeatureDoor.m_malfunctioning = ( ( Int32 )( EMalfunctioningType.LOUD_ANNOUNCEMENT ) );
		}
	}

}

