package cz.cuni.amis.pogamut.base.agent;

import java.util.EnumSet;
import java.util.Set;

/**
 * Basic agent states that describes the fundamental agent states.
 * <BR><BR>
 * <ol>
 * <li>INSTANTIATED - first state of the agent, it means 'was never started'</li>
 * <li>INIT - agent is being initialized</li>
 * <li>RUNNING - agent is running (it's logic whatever it is is running)</li>
 * <li>DEBUG_PAUSED - agent has been paused due to the breakpoint hit</li>
 * <li>PAUSED - agent is OK but it's execution has been paused</li>
 * <li>END - agent is terminated correctly</li>
 * <li>FAILED - agent has failed (usually because of the exception)</li>
 * <ol>
 * Even though this list may be extended in the future it is very unlikely.
 * <BR><BR>
 * There is a support for you to distinguish between three classes of states. Check out the methods
 * isXYZState() on the enum.
 * <ol>
 * <li>instantiatedState - agent was instantiated and never started (you may need to somehow
 * distinguish between agents that are initializing and those that are not, so this state
 * has been created)
 * <li>initState - agent is trying to start in the environment</li>
 * <li>okState  - agent is running in the environment</li>
 * <li>pausedState - agent is in the environment but it is paused (subset of okState)</li>
 * <li>endState - agent is terminated (or has failed), not connected to the environment</li>
 * </ol>
 * Every state is member exactly of one class.
 * 
 * @author Jimmy
 */
public enum AgentStateType {
	
	INSTANTIATED,
	INIT,
	RUNNING,
	DEBUG_PAUSED,
	PAUSED,
	END,
	FAILED;
	
	private static Set<AgentStateType> instantiatedStates = EnumSet.of(INSTANTIATED);
	private static Set<AgentStateType> initStates = EnumSet.of(INIT);
	private static Set<AgentStateType> okStates   = EnumSet.of(RUNNING, PAUSED, DEBUG_PAUSED);
	private static Set<AgentStateType> pausedStates = EnumSet.of(PAUSED, DEBUG_PAUSED);
	private static Set<AgentStateType> endStates  = EnumSet.of(END, FAILED);
		
	/**
	 * If true then agent was instantiated and never started (you may need to somehow
	 * distinguish between agents that are initializing and those that are not, so this state
	 * has been created)
	 * @return
	 */
	public boolean isInstantiatedState() {
		return instantiatedStates.contains(this);
	}
		
	/**
	 * If true then agent is trying to start intself in the environment.
	 * @return
	 */
	public boolean isInitState() {
		return initStates.contains(this);
	}
	
	/**
	 * If true then agent is running in the environment (but may be paused!).
	 * @return
	 */
	public boolean isOKState() {
		return okStates.contains(this);
	}
	
	/**
	 * If true then agent resides in the environment but it is paused (subset of okState).
	 * @return
	 */
	public boolean isPausedState() {
		return pausedStates.contains(this);
	}
	
	/**
	 * Agent is terminated (or has failed), not connected to the environment.
	 * @return
	 */
	public boolean isEndState() {
		return endStates.contains(this);
	}
	
}