/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package cz.cuni.amis.pogamut.base.agent.jmx;

import cz.cuni.amis.pogamut.base.agent.AgentState;
import cz.cuni.amis.pogamut.base.agent.AgentStateType;
import cz.cuni.amis.pogamut.base.agent.IAgent;
import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
import cz.cuni.amis.utils.flag.jmx.JMXFlagDecorator;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanNotificationInfo;
import javax.management.MalformedObjectNameException;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;

/**
 * Class for exporting arbitrary agents as managed MBeans.
 * @author Ik
 */
public class AgentMBeanAdapter implements AgentMBeanAdapterMBean {

    IAgent agent = null;
    JMXFlagDecorator<AgentState> jmxAgentState = null;
    
    public AgentMBeanAdapter(IAgent agent) {
        this.agent = agent;
        jmxAgentState = new JMXFlagDecorator<AgentState>(agent.getAgentState(), this, nbs);
    }

    /**
     * @param domain jmx domain
     * @return name under which the MBean should be exported
     */
    public ObjectName getObjectName(String domain) throws MalformedObjectNameException {
        return ObjectName.getInstance(domain + ":name=" + agent.getName() + ",type=agent");
    }

    public AgentState getAgentState() {
        return agent.getAgentState().getFlag();
    }

    /**
     * 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
     */
    public void start() throws AgentException {
        agent.start();
    }

    /**
     * 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 {
        agent.pause();
    }

    /**
     * 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 {
        agent.resume();
    }

    /**
     * Attempt to stop the agent, usually meaning dropping all running flags and see whether
     * it will stop automatically. 
     */
    public void stop() throws AgentException {
        agent.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.
     */
    public void kill() {
        agent.kill();
    }
    /**
     * Support object for sending notifications.
     */
    protected NotificationBroadcasterSupport nbs = new NotificationBroadcasterSupport();

    public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
        nbs.removeNotificationListener(listener, filter, handback);
    }

    public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
        nbs.addNotificationListener(listener, filter, handback);
    }

    public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
        nbs.removeNotificationListener(listener);
    }

    public MBeanNotificationInfo[] getNotificationInfo() {
        return new MBeanNotificationInfo[]{
                    jmxAgentState.getMBeanNotificationInfo()
                };
    }
}