/*
 * Java
 *
 * 2013-2022 ESR - Not subject to Copyright.
 *
 * This document has been released and published by E-S-R consortium, a non-profit entity.
 * To learn more about E-S-R consortium, please visit http://www.e-s-r.net/.
 * The matter contained in this document is not subject to copyright; you are free to use it for any purpose, for more information see E-S-R consortium policies.
 */
package ej.kf;

/**
 * <p>
 * A Feature represents an optional part of an application that adds new features and services.
 * </p>
 * <p>
 * A Feature only depends on Kernel code. A Feature is considered as unreliable code from Kernel point of view.
 * </p>
 * <p>
 * Instances of this class are owned by the Kernel.
 * </p>
 */
public class Feature extends Module {

	/**
	 * The minimum criticality that a feature can have.
	 *
	 * @see #getCriticality()
	 */
	public static final int MIN_CRITICALITY = 0;

	/**
	 * The default criticality that is assigned to a feature.
	 *
	 * @see #getCriticality()
	 */
	public static final int NORM_CRITICALITY = 5;

	/**
	 * The maximum criticality that a feature can have.
	 *
	 * @see #getCriticality()
	 */
	public static final int MAX_CRITICALITY = 10;

	/**
	 * A Feature state.
	 *
	 * @see Feature#getState()
	 */
	public static enum State {
		/**
		 * A Feature in the {@link #INSTALLED} state has been successfully linked to the Kernel and is not running.
		 * There are no references from the Kernel to objects owned by this Feature.
		 */
		INSTALLED,

		/**
		 * A Feature in the {@link #STARTED} state has been started and is running.
		 */
		STARTED,

		/**
		 * A Feature in the {@link #STOPPED} state has been stopped and all its threads are terminated. There are
		 * remaining references from the Kernel to objects owned by this Feature.
		 */
		STOPPED,

		/**
		 * A Feature in the {@link #UNINSTALLED} state has been unlinked from the Kernel. All Feature methods except
		 * {@link Feature#getState()} throw an {@link IllegalStateException}
		 */
		UNINSTALLED,
	}

	private Feature() {
		throw new RuntimeException(); // not in API
	}

	/**
	 * Gets a snapshot of all alive threads owned by this Feature (some threads included in the returned array may have
	 * been terminated when this method returns, some new threads may have been created when this method returns).
	 *
	 * @return the threads owned by this Feature
	 * @throws IllegalStateException
	 *             if the Feature is not in the {@link State#STARTED} state
	 */
	public Thread[] getAllAliveThreads() {
		throw new RuntimeException();
	}

	/**
	 * Returns the current Feature state.
	 *
	 * @return this Feature's state.
	 * @see State
	 */
	public State getState() {
		throw new RuntimeException();
	}

	/**
	 * Causes this Feature to start. A new thread owned by the Feature is created and started. The Feature is switched
	 * in the {@link State#STARTED} state and this method returns. Next steps are executed asynchronously within the new
	 * thread context:
	 * <ul>
	 * <li>Feature clinits are executed</li>
	 * <li>Entry point is instantiated</li>
	 * <li>{@link FeatureEntryPoint#start()} is called</li>
	 * </ul>
	 *
	 * @throws IllegalStateException
	 *             if the Feature state is not in {@link State#INSTALLED} state
	 */
	public void start() {
		throw new RuntimeException();
	}

	/**
	 * Causes this Feature to stop. The following steps are executed:
	 * <ul>
	 * <li>A new thread owned by the Feature is created and {@link FeatureEntryPoint#stop()} is executed.</li>
	 * <li>Wait until this thread is normally terminated or timeout occurred.</li>
	 * <li><code>ej.lang.Resource.reclaim()</code> is called for each resource that remains open by the Feature.</li>
	 * <li>A {@link DeadFeatureException} is thrown in threads that are running Feature code or in threads that want to
	 * call Feature code.</li>
	 * <li>Wait until all threads owned by this Feature are terminated.</li>
	 * <li>Feature state is set to {@link State#STOPPED}.</li>
	 * <li>Objects owned by the Feature are reclaimed. If there are no remaining alive objects, the Feature state is set
	 * to {@link State#INSTALLED}.
	 * </ul>
	 * <p>
	 * When the new Feature state is {@link State#INSTALLED}, the Feature runtime has been fully reclaimed (threads and
	 * objects). Otherwise, the new Feature state is {@link State#STOPPED} and there are some remaining Feature objects
	 * references from Kernel.
	 * </p>
	 * <p>
	 * This method can be called multiple times by the Kernel to reclaim objects again and thus to try to switch the
	 * Feature in the {@link State#INSTALLED} state.
	 * </p>
	 * <p>
	 * When Feature state is set to {@link State#STOPPED}, Kernel application shall remove all its references to objects
	 * owned by this Feature, through the calls of {@link FeatureStateListener#stateChanged}.
	 * </p>
	 *
	 * @throws IllegalStateException
	 *             if the Feature is in the {@link State#INSTALLED} or {@link State#UNINSTALLED} state
	 */
	public void stop() {
		throw new RuntimeException();
	}

	/**
	 * Returns the criticality of this feature.
	 * <p>
	 * The criticality is used by the system to determine which feature to kill when there is memory pressure. The
	 * features with the lowest criticality will be killed first. The features with a criticality set to
	 * {@link #MAX_CRITICALITY} are not killed automatically by the system when there is memory pressure.
	 * <p>
	 * The default criticality of a feature is {@link #NORM_CRITICALITY}.
	 * <p>
	 * If this feature is in {@link State#UNINSTALLED} state, this method returns {@link #NORM_CRITICALITY}.
	 *
	 * @return the criticality.
	 *
	 * @throws IllegalStateException
	 *             if this feature is in {@link State#UNINSTALLED} state.
	 */
	public int getCriticality() {
		throw new RuntimeException();
	}

	/**
	 * Sets the criticality of this feature.
	 * <p>
	 *
	 * @param criticality
	 *            the new criticality of this feature.
	 *
	 * @throws IllegalArgumentException
	 *             If the criticality is not in the range {@link #MIN_CRITICALITY} to {@link #MAX_CRITICALITY}.
	 *
	 * @see #getCriticality()
	 */
	public void setCriticality(int criticality) {
		throw new RuntimeException();
	}

}
