class QuickhackModule extends HUDModule
{
	private var m_calculateClose : Bool;

	public function SetCalculateClose( value : Bool )
	{
		m_calculateClose = value;
	}

	public const override function IsModuleOperational() : Bool
	{
		if( m_hud.IsBraindanceActive() )
		{
			return false;
		}
		if( m_hud.IsQuickHackPanelOpened() && m_hud.GetActiveMode() != ActiveMode.FOCUS )
		{
			return true;
		}
		if( m_hud.GetActiveMode() == ActiveMode.FOCUS )
		{
			return true;
		}
		return false;
	}

	protected override function Process( out task : HUDJob, mode : ActiveMode )
	{
		var instruction : QuickhackInstance;
		if( !( task.actor ) )
		{
			return;
		}
		if( m_hud.GetCurrentTarget() && ( ( ( m_hud.GetCurrentTarget().GetType() == HUDActorType.VEHICLE || m_hud.GetCurrentTarget().GetType() == HUDActorType.DEVICE ) || m_hud.GetCurrentTarget().GetType() == HUDActorType.BODY_DISPOSAL_DEVICE ) || m_hud.GetCurrentTarget().GetType() == HUDActorType.PUPPET ) )
		{
			if( task.actor == m_hud.GetCurrentTarget() )
			{
				if( m_hud.GetCurrentTarget().GetShouldRefreshQHack() )
				{
					m_calculateClose = true;
					m_hud.GetCurrentTarget().SetShouldRefreshQHack( false );
					instruction = task.instruction.quickhackInstruction;
					if( instruction && task.actor )
					{
						instruction.SetState( InstanceState.ON, DuplicateLastInstance( task.actor ) );
						instruction.SetContext( BaseOpenCheck() );
					}
				}
			}
		}
		else if( m_calculateClose )
		{
			m_calculateClose = false;
			m_hud.GetLastTarget().SetShouldRefreshQHack( true );
			SendRevealQuickhackMenu( m_hud, m_hud.GetPlayer().GetEntityID(), false );
		}
	}

	protected override function Process( out jobs : array< HUDJob >, mode : ActiveMode )
	{
		var i : Int32;
		for( i = 0; i < jobs.Size(); i += 1 )
		{
			Process( jobs[ i ], mode );
		}
	}

	public override function Suppress( jobs : ref< array< HUDJob > > )
	{
		var instruction : QuickhackInstance;
		var i : Int32;
		for( i = 0; i < jobs.Size(); i += 1 )
		{
			instruction = jobs[ i ].instruction.quickhackInstruction;
			instruction.SetState( InstanceState.DISABLED, DuplicateLastInstance( jobs[ i ].actor ) );
		}
	}

	protected override function DuplicateLastInstance( actor : HUDActor ) : QuickhackInstance
	{
		return ( ( QuickhackInstance )( super.DuplicateLastInstance( actor ) ) );
	}

	protected function BaseOpenCheck() : Bool
	{
		if( GetActiveMode() != ActiveMode.FOCUS )
		{
			return false;
		}
		if( IsQuickhackBlockedByScene( m_hud.GetPlayer() ) )
		{
			return false;
		}
		if( !( m_hud.IsCyberdeckEquipped() ) )
		{
			return false;
		}
		return true;
	}

	public static function IsQuickhackBlockedByScene( player : GameObject ) : Bool
	{
		var tier : Int32;
		tier = ( ( PlayerPuppet )( player ) ).GetPlayerStateMachineBlackboard().GetInt( GetAllBlackboardDefs().PlayerStateMachine.HighLevel );
		if( StatusEffectSystem.ObjectHasStatusEffectWithTag( player, 'NoQuickHacks' ) || ( ( tier >= ( ( Int32 )( gamePSMHighLevel.SceneTier3 ) ) ) && ( tier <= ( ( Int32 )( gamePSMHighLevel.SceneTier5 ) ) ) ) )
		{
			return true;
		}
		return false;
	}

	public static function RequestRefreshQuickhackMenu( context : GameInstance, requester : EntityID )
	{
		var self : HUDManager;
		self = ( ( HUDManager )( GameInstance.GetScriptableSystemsContainer( context ).Get( 'HUDManager' ) ) );
		if( self )
		{
			if( self.IsQuickHackPanelOpened() && ( self.GetCurrentTargetID() == requester ) )
			{
				SendRevealQuickhackMenu( self, requester, true );
			}
		}
	}

	public static function RequestCloseQuickhackMenu( context : GameInstance, requester : EntityID )
	{
		var self : HUDManager;
		self = ( ( HUDManager )( GameInstance.GetScriptableSystemsContainer( context ).Get( 'HUDManager' ) ) );
		if( self )
		{
			SendRevealQuickhackMenu( self, requester, false );
		}
	}

	private static function SendRevealQuickhackMenu( hudManager : HUDManager, requester : EntityID, shouldOpen : Bool )
	{
		var request : RevealQuickhackMenu;
		request = new RevealQuickhackMenu;
		request.shouldOpenWheel = shouldOpen;
		request.ownerID = requester;
		hudManager.QueueRequest( request );
	}

	public static function TranslateEmptyQuickSlotCommands( context : GameInstance ) : array< QuickhackData >
	{
		var commands : array< QuickhackData >;
		var newCommand : QuickhackData;
		newCommand = new QuickhackData;
		newCommand.m_title = "LocKey#42170";
		newCommand.m_isLocked = true;
		newCommand.m_description = "LocKey#34276";
		newCommand.m_inactiveReason = "LocKey#27694";
		newCommand.m_actionState = EActionInactivityReson.Invalid;
		newCommand.m_noQuickhackData = true;
		commands.PushBack( newCommand );
		return commands;
	}

	private function SendFakeCommands( const commands : ref< array< QuickhackData > >, shouldReveal : Bool )
	{
		var quickSlotsManagerNotification : RevealInteractionWheel;
		var playerRef : PlayerPuppet;
		playerRef = ( ( PlayerPuppet )( GetPlayer() ) );
		quickSlotsManagerNotification = new RevealInteractionWheel;
		quickSlotsManagerNotification.lookAtObject = NULL;
		quickSlotsManagerNotification.shouldReveal = shouldReveal;
		quickSlotsManagerNotification.commands = commands;
		m_hud.QueueEntityEvent( playerRef.GetEntityID(), quickSlotsManagerNotification );
	}

	public static function CheckCommandDuplicates( commands : ref< array< QuickhackData > >, optional characterRecord : weak< Character_Record > )
	{
		var remove : Bool;
		var removeIndexes : array< Int32 >;
		var actionRectord : weak< ObjectAction_Record >;
		var i, i1 : Int32;
		for( i = commands.Size() - 1; i >= 0; i -= 1 )
		{
			remove = false;
			for( i1 = 0; i1 < commands.Size(); i1 += 1 )
			{
				if( i <= i1 )
				{
					break;
				}
				if( commands[ i ].m_title == commands[ i1 ].m_title )
				{
					remove = true;
					break;
				}
			}
			if( remove )
			{
				if( characterRecord )
				{
					if( commands[ i ].m_action )
					{
						if( characterRecord.ObjectActionsContains( ( ( BaseScriptableAction )( commands[ i ].m_action ) ).GetObjectActionRecord() ) )
						{
							removeIndexes.PushBack( i1 );
							continue;
						}
					}
					if( commands[ i1 ].m_action )
					{
						actionRectord = ( ( BaseScriptableAction )( commands[ i1 ].m_action ) ).GetObjectActionRecord();
						if( characterRecord.ObjectActionsContains( actionRectord ) )
						{
							removeIndexes.PushBack( i );
							continue;
						}
					}
					removeIndexes.PushBack( i );
				}
				else
				{
					if( removeIndexes.Contains( i ) )
					{
						removeIndexes.PushBack( i1 );
					}
					else if( removeIndexes.Contains( i1 ) )
					{
						removeIndexes.PushBack( i );
					}
					else if( commands[ i ].m_actionMatchesTarget )
					{
						removeIndexes.PushBack( i1 );
					}
					else
					{
						removeIndexes.PushBack( i );
					}
				}
			}
		}
		for( i = 0; i < removeIndexes.Size(); i += 1 )
		{
			commands[ removeIndexes[ i ] ] = NULL;
		}
		for( i = commands.Size() - 1; i >= 0; i -= 1 )
		{
			if( !( commands[ i ] ) )
			{
				commands.Erase( i );
			}
		}
	}

	public static function SortCommandPriority( commands : ref< array< QuickhackData > >, context : GameInstance )
	{
		var sortedArray : array< QuickhackData >;
		var i, activeIndex : Int32;
		var actionTDB : TweakDBID;
		activeIndex = -1;
		for( i = commands.Size() - 1; i >= 0; i -= 1 )
		{
			if( !( commands[ i ].m_isLocked ) || commands[ i ].m_actionMatchesTarget )
			{
				actionTDB = ( ( BaseScriptableAction )( commands[ i ].m_action ) ).GetObjectActionID();
				if( ( ( actionTDB == T"QuickHack.RemoteBreach" ) || ( actionTDB == T"DeviceAction.RemoteBreach" ) ) || ( actionTDB == T"QuickHack.ICEBreakerHack" ) )
				{
					sortedArray.Insert( 0, commands[ i ] );
				}
				else
				{
					sortedArray.PushBack( commands[ i ] );
				}
				commands.Erase( i );
				activeIndex += 1;
			}
		}
		if( !( NetworkSystem.ShouldShowOnlyTargetQuickHacks( context ) ) )
		{
			for( i = 0; i < commands.Size(); i += 1 )
			{
				if( commands[ i ].m_isLocked )
				{
					sortedArray.PushBack( commands[ i ] );
				}
			}
		}
		if( sortedArray.Size() == 0 )
		{
			sortedArray = QuickhackModule.TranslateEmptyQuickSlotCommands( context );
			for( i = 0; i < sortedArray.Size(); i += 1 )
			{
				sortedArray[ i ].m_inactiveReason = "LocKey#34276";
				sortedArray[ i ].m_title = "LocKey#42171";
			}
		}
		commands = sortedArray;
	}

}

class QuickhackInstance extends ModuleInstance
{
	private var open : Bool;
	private var process : Bool;

	public function ShouldOpen() : Bool
	{
		return open;
	}

	public function ShouldProcess() : Bool
	{
		return process;
	}

	public function SetContext( _open : Bool )
	{
		process = true;
		open = _open;
	}

}

class CloseQHmenu extends Event
{
}

