class SecurityTurretOffline extends Event
{
}

class RipOff extends ActionBool
{

	public function SetProperties()
	{
		actionName = 'RipOff';
		prop = DeviceActionPropertyFunctions.SetUpProperty_Bool( actionName, true, 'LocKey#383', 'LocKey#383' );
	}

	public override function GetTweakDBChoiceRecord() : String
	{
		return "RipOff";
	}

}

class QuestForceReload extends ActionBool
{

	public function SetProperties()
	{
		actionName = 'ForceReload';
		prop = DeviceActionPropertyFunctions.SetUpProperty_Bool( 'QuestForceReload', true, 'QuestForceReload', 'QuestForceReload' );
	}

}

class QuestForceOverheat extends ActionBool
{

	public function SetProperties()
	{
		actionName = 'ForceOverheat';
		prop = DeviceActionPropertyFunctions.SetUpProperty_Bool( 'QuestForceOverheat', true, 'QuestForceOverheat', 'QuestForceOverheat' );
	}

}

class QuestRemoveWeapon extends ActionBool
{

	public function SetProperties()
	{
		actionName = 'RemoveWeapon';
		prop = DeviceActionPropertyFunctions.SetUpProperty_Bool( 'QuestRemoveWeapon', true, 'QuestRemoveWeapon', 'QuestRemoveWeapon' );
	}

}

class SecurityTurretStatus extends BaseDeviceStatus
{

	public override function SetProperties( const deviceRef : ScriptableDeviceComponentPS )
	{
		super.SetProperties( deviceRef );
	}

	public const override function GetCurrentDisplayString() : String
	{
		return super.GetCurrentDisplayString();
	}

	public static function IsDefaultConditionMet( device : ScriptableDeviceComponentPS, const context : ref< GetActionsContext > ) : Bool
	{
		if( IsAvailable( device ) && IsClearanceValid( context.clearance ) )
		{
			return true;
		}
		return false;
	}

	public static function IsAvailable( device : ScriptableDeviceComponentPS ) : Bool
	{
		return BaseDeviceStatus.IsAvailable( device );
	}

	public static function IsClearanceValid( clearance : Clearance ) : Bool
	{
		return BaseDeviceStatus.IsClearanceValid( clearance );
	}

	public static function IsContextValid( const context : ref< GetActionsContext > ) : Bool
	{
		return BaseDeviceStatus.IsContextValid( context );
	}

	public override function GetTweakDBChoiceRecord() : String
	{
		return "wrong_action";
	}

}

class SecurityTurretController extends SensorDeviceController
{

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

}

class SecurityTurretControllerPS extends SensorDeviceControllerPS
{
	default m_deviceName = "LocKey#121";
	default m_tweakDBRecord = T"Devices.SecurityTurret";
	default m_tweakDBDescriptionRecord = T"device_descriptions.SecurityTurret";
	default m_canPlayerTakeOverControl = true;
	default m_lookAtPresetVert = T"LookatPreset.TurretVertical";
	default m_lookAtPresetHor = T"LookatPreset.TurretHorizontal";
	private persistent var m_pendingSecuritySystemDisableRequest : Bool;
	private instanceeditable inlined var m_turretSkillChecks : EngDemoContainer;
	protected editable var m_ignoreSkillcheckGeneration : Bool;
	[ category = "Game effect refs" ]
	protected editable var m_laserGameEffectRef : EffectRef;
	[ category = "Weapon custom override" ]
	private editable var m_weaponItemRecordString : String;
	[ category = "Weapon custom override" ]
	private editable var m_vfxNameOnShoot : CName;

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

	protected override function Initialize()
	{
		super.Initialize();
		if( !( IsFinal() ) )
		{
			if( GameInstance.GetRuntimeInfo( GetGameInstance() ).IsGamePreview() )
			{
				if( PreviewConfig_DisableTurrets() )
				{
					ExecutePSAction( ActionQuestForceDisabled() );
					SetBlockSecurityWakeUp( true );
				}
			}
		}
	}

	protected override function GameAttached() {}

	protected override function GetSkillCheckContainerForSetup() : BaseSkillCheckContainer
	{
		if( !( m_ignoreSkillcheckGeneration ) )
		{
			return m_turretSkillChecks;
		}
		return NULL;
	}

	protected override final function SetDeviceState( state : EDeviceStatus )
	{
		super.SetDeviceState( state );
		if( ( ( Int32 )( state ) ) <= ( ( Int32 )( EDeviceStatus.UNPOWERED ) ) )
		{
			SendDeviceNotOperationalEvent();
		}
	}

	public const function GetIsUnderControl() : Bool
	{
		return m_isControlledByThePlayer;
	}

	public const function GetLaserGameEffectRef() : EffectRef
	{
		return m_laserGameEffectRef;
	}

	public const override function GetDeviceStatusAction() : SecurityTurretStatus
	{
		return ActionSecurityTurretStatus();
	}

	public const function GetVfxNameOnShoot() : String
	{
		return ( ( String )( m_vfxNameOnShoot ) );
	}

	public const function GetWeaponItemRecordString() : String
	{
		return m_weaponItemRecordString;
	}

	private const function ActionSecurityTurretStatus() : SecurityTurretStatus
	{
		var action : SecurityTurretStatus;
		action = new SecurityTurretStatus;
		action.clearanceLevel = DefaultActionsParametersHolder.GetStatusClearance();
		action.SetUp( this );
		action.SetProperties( this );
		action.AddDeviceName( m_deviceName );
		return action;
	}

	public override function GetQuestActionByName( actionName : CName ) : DeviceAction
	{
		var action : DeviceAction;
		action = super.GetQuestActionByName( actionName );
		if( action == NULL )
		{
			switch( actionName )
			{
				case 'QuestFollowTarget':
					action = ActionQuestFollowTarget();
				break;
				case 'QuestStopFollowingTarget':
					action = ActionQuestStopFollowingTarget();
				break;
				case 'QuestLookAtTarget':
					action = ActionQuestLookAtTarget();
				break;
				case 'QuestStopLookAtTarget':
					action = ActionQuestStopLookAtTarget();
				break;
				case 'QuestForceTakeControlOverCamera':
					action = ActionQuestForceTakeControlOverCamera();
				break;
				case 'QuestForceStopTakeControlOverCamera':
					action = ActionQuestForceStopTakeControlOverCamera();
				break;
				case 'QuestForceAttitude':
					action = ActionQuestForceAttitude();
				break;
				case 'QuestResetDeviceToInitialState':
					action = ActionQuestResetDeviceToInitialState();
				break;
				case 'ForceReload':
					action = ActionQuestForceReload();
				break;
				case 'ForceOverheat':
					action = ActionQuestForceOverheat();
				break;
				case 'RemoveWeapon':
					action = ActionQuestRemoveWeapon();
				break;
				case 'QuestSetDetectionToTrue':
					action = ActionQuestSetDetectionToTrue();
				break;
				case 'QuestSetDetectionToFalse':
					action = ActionQuestSetDetectionToFalse();
				break;
				case 'QuestSpotTargetReference':
					action = ActionQuestSpotTargetReference();
				break;
			}
		}
		return action;
	}

	public override function GetQuestActions( out actions : array< DeviceAction >, const context : ref< GetActionsContext > )
	{
		super.GetQuestActions( actions, context );
		actions.PushBack( ActionQuestFollowTarget() );
		actions.PushBack( ActionQuestStopFollowingTarget() );
		actions.PushBack( ActionQuestLookAtTarget() );
		actions.PushBack( ActionQuestStopLookAtTarget() );
		actions.PushBack( ActionQuestForceTakeControlOverCamera() );
		actions.PushBack( ActionQuestForceStopTakeControlOverCamera() );
		actions.PushBack( ActionQuestForceAttitude() );
		actions.PushBack( ActionQuestResetDeviceToInitialState() );
		actions.PushBack( ActionQuestForceReload() );
		actions.PushBack( ActionQuestForceOverheat() );
		actions.PushBack( ActionQuestRemoveWeapon() );
		actions.PushBack( ActionQuestSetDetectionToTrue() );
		actions.PushBack( ActionQuestSetDetectionToFalse() );
		actions.PushBack( ActionQuestSpotTargetReference() );
	}

	protected virtual function ActionRipOff() : RipOff
	{
		var action : RipOff;
		action = new RipOff;
		action.clearanceLevel = DefaultActionsParametersHolder.GetTakeOverControl();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		return action;
	}

	public function OnRipOff( evt : RipOff ) : EntityNotificationType
	{
		ExecutePSAction( ActionQuestForceDisabled() );
		SetBlockSecurityWakeUp( true );
		evt.GetExecutor().QueueEvent( evt );
		UseNotifier( evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	public override function GetActions( out actions : array< DeviceAction >, context : GetActionsContext ) : Bool
	{
		if( StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayer( GetGameInstance() ), 'FistFight' ) || StatusEffectSystem.ObjectHasStatusEffectWithTag( GetPlayer( GetGameInstance() ), 'Melee' ) )
		{
			return false;
		}
		if( !( super.GetActions( actions, context ) ) )
		{
			return false;
		}
		if( ToggleON.IsDefaultConditionMet( this, context ) && ( context.requestType != gamedeviceRequestType.Direct && context.requestType != gamedeviceRequestType.Remote ) )
		{
			actions.PushBack( ActionToggleON() );
		}
		if( RipOff.IsDefaultConditionMet( this, context ) && context.requestType == gamedeviceRequestType.Direct )
		{
			actions.PushBack( ActionRipOff() );
		}
		if( ( ( ToggleTakeOverControl.IsDefaultConditionMet( this, context ) && m_canPlayerTakeOverControl ) && context.requestType == gamedeviceRequestType.External ) || m_isControlledByThePlayer )
		{
			actions.PushBack( ActionToggleTakeOverControl() );
		}
		SetActionIllegality( actions, m_illegalActions.regularActions );
		return true;
	}

	protected const override function CanCreateAnyQuickHackActions() : Bool
	{
		if( GetDurabilityState() == EDeviceDurabilityState.NOMINAL )
		{
			return true;
		}
		else
		{
			return false;
		}
	}

	protected override function GetQuickHackActions( out actions : array< DeviceAction >, const context : ref< GetActionsContext > )
	{
		var currentAction : ScriptableDeviceAction;
		if( GetDurabilityState() == EDeviceDurabilityState.NOMINAL )
		{
			super.GetQuickHackActions( actions, context );
			currentAction = ActionSetDeviceAttitude();
			currentAction.SetObjectActionID( T"DeviceAction.TurretOverrideAttitudeClassLvl5Hack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsON(), "LocKey#7005" );
			currentAction.SetInactiveWithReason( IsAttitudeFromContextHostile(), "LocKey#7010" );
			actions.PushBack( currentAction );
			currentAction = ActionSetDeviceAttitude();
			currentAction.SetObjectActionID( T"DeviceAction.TurretOverrideAttitudeClassHack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsON(), "LocKey#7005" );
			currentAction.SetInactiveWithReason( IsAttitudeFromContextHostile(), "LocKey#7010" );
			actions.PushBack( currentAction );
			currentAction = ActionToggleTakeOverControl();
			currentAction.SetObjectActionID( T"DeviceAction.TakeControlClassHack" );
			currentAction.SetInactiveWithReason( m_canPlayerTakeOverControl, "LocKey#7006" );
			currentAction.SetInactiveWithReason( IsON(), "LocKey#7005" );
			currentAction.SetInactiveWithReason( !( PlayerPuppet.IsSwimming( GetPlayer( GetGameInstance() ) ) ), "LocKey#7003" );
			currentAction.SetInactiveWithReason( PlayerPuppet.GetSceneTier( GetPlayer( GetGameInstance() ) ) <= ( ( Int32 )( gamePSMHighLevel.SceneTier1 ) ), "LocKey#7003" );
			actions.PushBack( currentAction );
			currentAction = ActionSetDeviceTagKillMode();
			currentAction.SetObjectActionID( T"DeviceAction.SetDeviceTagKillMode" );
			currentAction.SetInactiveWithReason( !( IsInTagKillMode() ), "LocKey#7004" );
			actions.PushBack( currentAction );
			currentAction = ActionQuickHackToggleON();
			currentAction.SetObjectActionID( T"DeviceAction.TurretToggleStateClassHack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsOFFTimed(), "LocKey#7005" );
			actions.PushBack( currentAction );
			currentAction = ActionQuickHackToggleON();
			currentAction.SetObjectActionID( T"DeviceAction.TurretToggleStateClassLvl2Hack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsOFFTimed(), "LocKey#7005" );
			actions.PushBack( currentAction );
			currentAction = ActionQuickHackToggleON();
			currentAction.SetObjectActionID( T"DeviceAction.TurretToggleStateClassLvl3Hack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsOFFTimed(), "LocKey#7005" );
			actions.PushBack( currentAction );
			currentAction = ActionQuickHackToggleON();
			currentAction.SetObjectActionID( T"DeviceAction.TurretToggleStateClassLvl4Hack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsOFFTimed(), "LocKey#7005" );
			actions.PushBack( currentAction );
			currentAction = ActionQuickHackToggleON();
			currentAction.SetObjectActionID( T"DeviceAction.TurretToggleStateClassLvl5Hack" );
			currentAction.SetExecutor( GetPlayer( GetGameInstance() ) );
			currentAction.SetDurationValue( currentAction.GetDurationTime() );
			currentAction.SetInactiveWithReason( IsOFFTimed(), "LocKey#7005" );
			actions.PushBack( currentAction );
		}
		FinalizeGetQuickHackActions( actions, context );
	}

	protected override function ActionSetDeviceAttitude() : SetDeviceAttitude
	{
		var action : SetDeviceAttitude;
		action = new SetDeviceAttitude;
		action.Repeat = true;
		action.clearanceLevel = DefaultActionsParametersHolder.GetTakeOverControl();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		action.CreateInteraction();
		return action;
	}

	protected override function GetMinigameActions( actions : ref< array< DeviceAction > >, const context : ref< GetActionsContext > )
	{
		var action : ScriptableDeviceAction;
		action = ActionProgramSetDeviceOff();
		action.clearanceLevel = DefaultActionsParametersHolder.GetInteractiveClearance();
		action.SetUp( this );
		action.AddDeviceName( m_deviceName );
		actions.PushBack( action );
		action = ActionProgramSetDeviceAttitude();
		action.clearanceLevel = DefaultActionsParametersHolder.GetInteractiveClearance();
		action.SetUp( this );
		action.AddDeviceName( m_deviceName );
		actions.PushBack( action );
	}

	private export function OnPendingSecuritySystemDisable( evt : PendingSecuritySystemDisable ) : EntityNotificationType
	{
		m_pendingSecuritySystemDisableRequest = evt.isPending;
		return EntityNotificationType.DoNotNotifyEntity;
	}

	public export override function OnSecuritySystemOutput( evt : SecuritySystemOutput ) : EntityNotificationType
	{
		super.OnSecuritySystemOutput( evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	public export override function OnSecurityAreaCrossingPerimeter( evt : SecurityAreaCrossingPerimeter ) : EntityNotificationType
	{
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected const override function CanPerformReprimand() : Bool
	{
		return true;
	}

	protected override function ActionEngineering( const context : ref< GetActionsContext > ) : ActionEngineering
	{
		var action : ActionEngineering;
		var displayName : String;
		action = super.ActionEngineering( context );
		displayName = "Override";
		action.ResetCaption();
		action.CreateInteraction( context.processInitiatorObject, , displayName );
		return action;
	}

	public override function OnActionEngineering( evt : ActionEngineering ) : EntityNotificationType
	{
		if( !( evt.WasPassed() ) )
		{
			return EntityNotificationType.DoNotNotifyEntity;
		}
		super.OnActionEngineering( evt );
		if( evt.IsCompleted() )
		{
			Override( evt );
			RPGManager.GiveReward( evt.GetExecutor().GetGame(), T"RPGActionRewards.ExtractPartsSecurityTurret" );
			return EntityNotificationType.SendThisEventToEntity;
		}
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected override function ActionDemolition( const context : ref< GetActionsContext > ) : ActionDemolition
	{
		var action : ActionDemolition;
		var displayName : String;
		action = super.ActionDemolition( context );
		displayName = "RipOff";
		action.ResetCaption();
		action.SetAvailableOnUnpowered();
		action.CreateInteraction( context.processInitiatorObject, , displayName );
		return action;
	}

	public override function OnActionDemolition( evt : ActionDemolition ) : EntityNotificationType
	{
		if( !( evt.WasPassed() ) )
		{
			return EntityNotificationType.DoNotNotifyEntity;
		}
		super.OnActionDemolition( evt );
		if( evt.IsCompleted() )
		{
			RipOff( evt );
			return EntityNotificationType.SendPSChangedEventToEntity;
		}
		return EntityNotificationType.DoNotNotifyEntity;
	}

	private function Override( action : ScriptableDeviceAction )
	{
		var actionToSend : ScriptableDeviceAction;
		actionToSend = ActionSetDeviceAttitude();
		actionToSend.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
		actionToSend.SetExecutor( action.GetExecutor() );
		GetPersistencySystem().QueuePSDeviceEvent( actionToSend );
	}

	private function RipOff( action : ScriptableDeviceAction )
	{
		var actionToSend : ScriptableDeviceAction;
		actionToSend = ActionRipOff();
		actionToSend.RegisterAsRequester( PersistentID.ExtractEntityID( GetID() ) );
		actionToSend.SetExecutor( action.GetExecutor() );
		GetPersistencySystem().QueuePSDeviceEvent( actionToSend );
	}

	public override function OnDisassembleDevice( evt : DisassembleDevice ) : EntityNotificationType
	{
		TurnAuthorizationModuleOFF();
		m_disassembleProperties.m_canBeDisassembled = false;
		UseNotifier( evt );
		if( !( IsFinal() ) )
		{
		}
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected function ActionQuestForceReload() : QuestForceReload
	{
		var action : QuestForceReload;
		action = new QuestForceReload;
		action.clearanceLevel = DefaultActionsParametersHolder.GetQuestClearance();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		return action;
	}

	public virtual function OnQuestForceReload( evt : QuestForceReload ) : EntityNotificationType
	{
		var notifier : ActionNotifier;
		notifier = new ActionNotifier;
		notifier.SetNone();
		Notify( notifier, evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected function ActionQuestForceOverheat() : QuestForceOverheat
	{
		var action : QuestForceOverheat;
		action = new QuestForceOverheat;
		action.clearanceLevel = DefaultActionsParametersHolder.GetQuestClearance();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		return action;
	}

	public virtual function OnQuestForceOverheat( evt : QuestForceOverheat ) : EntityNotificationType
	{
		var notifier : ActionNotifier;
		notifier = new ActionNotifier;
		notifier.SetNone();
		Notify( notifier, evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	protected function ActionQuestRemoveWeapon() : QuestRemoveWeapon
	{
		var action : QuestRemoveWeapon;
		action = new QuestRemoveWeapon;
		action.clearanceLevel = DefaultActionsParametersHolder.GetQuestClearance();
		action.SetUp( this );
		action.SetProperties();
		action.AddDeviceName( m_deviceName );
		return action;
	}

	public virtual function OnQuestRemoveWeapon( evt : QuestRemoveWeapon ) : EntityNotificationType
	{
		var notifier : ActionNotifier;
		notifier = new ActionNotifier;
		notifier.SetNone();
		Notify( notifier, evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

	public override function ActionProgramSetDeviceOff() : ProgramSetDeviceOff
	{
		var action : ProgramSetDeviceOff;
		var multiplier : Float;
		action = super.ActionProgramSetDeviceOff();
		multiplier = GameInstance.GetStatsSystem( GetGameInstance() ).GetStatValue( GetPlayer( GetGameInstance() ).GetEntityID(), gamedataStatType.TurretShutdownExtension );
		action.SetDurationValue( action.GetDurationFromTDBRecord( T"MinigameAction.NetworkTurretShutdown" ) * multiplier );
		return action;
	}

	public override function ActionProgramSetDeviceAttitude() : ProgramSetDeviceAttitude
	{
		var action : ProgramSetDeviceAttitude;
		var multiplier : Float;
		action = super.ActionProgramSetDeviceAttitude();
		multiplier = GameInstance.GetStatsSystem( GetGameInstance() ).GetStatValue( GetPlayer( GetGameInstance() ).GetEntityID(), gamedataStatType.TurretFriendlyExtension );
		action.SetDurationValue( action.GetDurationFromTDBRecord( T"MinigameAction.NetworkTurretFriendly" ) * multiplier );
		return action;
	}

	public override function SendDeviceNotOperationalEvent()
	{
		var areas : array< SecurityAreaControllerPS >;
		var i : Int32;
		if( m_pendingSecuritySystemDisableRequest && !( IsTurretOperationalUnderSecuritySystem() ) )
		{
			areas = GetSecurityAreas();
			for( i = 0; i < areas.Size(); i += 1 )
			{
				QueuePSEvent( areas[ i ], new SecurityTurretOffline );
			}
			m_pendingSecuritySystemDisableRequest = false;
		}
	}

	public const function IsTurretOperationalUnderSecuritySystem() : Bool
	{
		var isOperational : Bool;
		var turret : SecurityTurret;
		var groupName : CName;
		turret = ( ( SecurityTurret )( GetOwnerEntityWeak() ) );
		groupName = turret.GetAttitudeAgent().GetAttitudeGroup();
		isOperational = ( ( !( IsControlledByPlayer() ) && !( IsSecurityWakeUpBlocked() ) ) && groupName != 'player' ) && IsPowered();
		return isOperational;
	}

	protected export override function OnSetDeviceAttitude( evt : SetDeviceAttitude ) : EntityNotificationType
	{
		super.OnSetDeviceAttitude( evt );
		return EntityNotificationType.SendThisEventToEntity;
	}

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

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

}

