abstract class HUDModule extends IScriptable
{
	protected var m_hud : weak< HUDManager >;
	protected var m_state : ModuleState;
	protected var m_instancesList : array< ModuleInstance >;

	public const function GetState() : ModuleState
	{
		return m_state;
	}

	public const virtual function IsModuleOperational() : Bool
	{
		return m_state == ModuleState.ON || m_state == ModuleState.MALFUNCTIONING;
	}

	public function InitializeModule( hud : weak< HUDManager >, state : ModuleState )
	{
		if( !( hud ) )
		{
			return;
		}
		m_hud = hud;
		m_state = state;
	}

	public virtual function UnregisterActor( actor : HUDActor )
	{
		var i : Int32;
		if( !( actor ) )
		{
			return;
		}
		for( i = 0; i < m_instancesList.Size(); i += 1 )
		{
			if( m_instancesList[ i ].GetEntityID() == actor.GetEntityID() )
			{
				m_instancesList.Erase( i );
				return;
			}
		}
	}

	protected function OverrideInstance( index : Int32, instance : ModuleInstance )
	{
		if( IsIndexOK( index ) )
		{
			m_instancesList[ index ] = instance;
		}
	}

	protected virtual function DuplicateLastInstance( actor : HUDActor ) : ModuleInstance
	{
		var i : Int32;
		var instanceDuplicate : ModuleInstance;
		return NULL;
		if( !( actor ) )
		{
			return NULL;
		}
		for( i = 0; i < m_instancesList.Size(); i += 1 )
		{
			if( m_instancesList[ i ].GetEntityID() == actor.GetEntityID() )
			{
				instanceDuplicate = new ModuleInstance;
				instanceDuplicate = m_instancesList[ i ];
				return instanceDuplicate;
			}
		}
		return NULL;
	}

	protected function IsIndexOK( index : Int32 ) : Bool
	{
		if( ( index < 0 ) || ( index > ( m_instancesList.Size() - 1 ) ) )
		{
			return false;
		}
		return true;
	}

	public function Iterate( out jobs : array< HUDJob >, optional forcedMode : ActiveMode )
	{
		if( IsModuleOperational() )
		{
			if( forcedMode == ActiveMode.UNINITIALIZED )
			{
				forcedMode = GetActiveMode();
			}
			Process( jobs, forcedMode );
		}
	}

	public function Iterate( out job : HUDJob, optional forcedMode : ActiveMode )
	{
		if( IsModuleOperational() )
		{
			if( forcedMode == ActiveMode.UNINITIALIZED )
			{
				forcedMode = GetActiveMode();
			}
			Process( job, forcedMode );
		}
	}

	public virtual function Suppress( jobs : ref< array< HUDJob > > ) {}

	protected virtual function Process( out jobs : array< HUDJob >, mode : ActiveMode ) {}

	protected virtual function Process( out task : HUDJob, mode : ActiveMode ) {}

	protected const function GetPlayer() : GameObject
	{
		return m_hud.GetPlayer();
	}

	protected virtual function GetActiveMode() : ActiveMode
	{
		return m_hud.GetActiveMode();
	}

	protected const function IsActorLookedAt( actor : HUDActor ) : Bool
	{
		return m_hud.GetCurrentTarget() == actor;
	}

	protected const function IsActorQuickHackTarget( actor : HUDActor ) : Bool
	{
		return m_hud.GetQuickHackTargetID() == actor.GetEntityID();
	}

	protected const function HasCurrentTarget() : Bool
	{
		return m_hud.HasCurrentTarget();
	}

	protected const function IsActorLooted( actor : HUDActor ) : Bool
	{
		return m_hud.GetLootedTargetID() == actor.GetEntityID();
	}

}

class ModuleInstance extends IScriptable
{
	var isLookedAt : Bool;
	var isRevealed : Bool;
	var wasProcessed : Bool;
	protected var entityID : EntityID;
	protected var state : InstanceState;
	protected var previousInstance : ModuleInstance;

	public function SetContext( _isLookedAt : Bool, _isRevealed : Bool )
	{
		isLookedAt = _isLookedAt;
		isRevealed = _isRevealed;
	}

	public static function Construct( self : ModuleInstance, id : EntityID )
	{
		if( EntityID.IsDefined( id ) )
		{
			self.entityID = id;
			self.wasProcessed = false;
		}
	}

	public const function GetEntityID() : EntityID
	{
		return entityID;
	}

	public const function GetState() : InstanceState
	{
		return state;
	}

	public const function IsLookedAt() : Bool
	{
		return isLookedAt;
	}

	public const function IsRevealed() : Bool
	{
		return isRevealed;
	}

	public const function WasProcessed() : Bool
	{
		return wasProcessed;
	}

	public virtual function SetState( newState : InstanceState, _previousInstance : ModuleInstance )
	{
		state = newState;
		previousInstance = _previousInstance;
		wasProcessed = true;
	}

}

