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

import cz.cuni.amis.introspection.Folder;
import java.util.concurrent.Future;

import javax.management.MXBean;

import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
import cz.cuni.amis.pogamut.base.factory.guice.AgentScoped;
import cz.cuni.amis.pogamut.base.utils.IControllable;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;
import cz.cuni.amis.utils.flag.ImmutableFlag;

/**
 * MXBean interface - serves the purpose only to JMX, you should always derive your agent from
 * at least AbstractAgent, even though it's not enforced right now it may be in the future!
 * 
 * @author Jimmy
 */
@MXBean
@AgentScoped
public interface IAgent extends IControllable {
	
	/**
     * Unique agent name.
     */
     public String getName();
	
	/**
	 * Returns AgentLogger for the instance allowing creating new log categories
	 * or adding new handlers to them.
	 * 
	 * @return
	 */
	public AgentLogger getLogger();
	
	/**
	 * Returns the state of the agent (whether it's running / dead / etc.).
	 * <p><p>
	 * Note that the type AgentState wraps two things: 
	 * <ul>
	 * <li>AgentStateType that describes the type of the state (init, running, paused, etc.)</li>
	 * <li>String description of the state</li>
	 * </ul>
	 * 
	 * @return
	 */
	public ImmutableFlag<AgentState> getAgentState();
	
	/**
	 * Attempt to launch the agent.
	 * <BR><BR>
	 * Returns Future with the result of the start, it's get() method will block until
	 * the agent reaches one of it's "ok" or "end" states (see AgentState doc).
	 * 
	 * @return future object describing success, whether the agent has been started or not.
	 * @throws AgentException
	 */
	@Override
	public void start() throws AgentException;
	
	/**
	 * This should pause the logic of the agent. It should also be reflected in the agent state.
	 * <BR><BR>
	 * If your agent can't be paused, throw OperationNotSupportedException.
	 */
	public void pause() throws AgentException;
	
	/**
	 * This should resume the logic of the agent. It should also be reflected in the agent state.
	 * <BR><BR>
	 * If your agent can't be paused therefore can't be resumed,
	 * throw OperationNotSupportedException.
	 * 
	 * @return
	 */
	public void resume() throws AgentException;
	
	/**
	 * Attempt to stop the agent, usually meaning dropping all running flags and see whether
	 * it will stop automatically. 
	 */
	@Override
	public void stop();
	
	/**
	 * Stops the agent (unconditionally), closing whatever connection it may have, this
	 * method must be non-blocking + interrupting all the communication, logic, whatever
	 * threads the agent have.
	 */
	@Override
	public void kill();
        
    /**
     * Returns folder with introspection information. Useful for showing model 
     * variables and parameters.
     * @return Folder with introspection info
     */
    public Folder getFolder();
    
}
