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

import com.google.inject.Inject;

import cz.cuni.amis.pogamut.base.agent.exceptions.AgentException;
import cz.cuni.amis.pogamut.base.agent.worldview.IStartableWorldView;
import cz.cuni.amis.pogamut.base.agent.worldview.IWorldView;
import cz.cuni.amis.pogamut.base.exceptions.PogamutException;
import cz.cuni.amis.pogamut.base.factory.guice.AgentScoped;
import cz.cuni.amis.pogamut.base.utils.logging.AgentLogger;
import cz.cuni.amis.utils.flag.FlagListener;
import java.util.concurrent.CountDownLatch;

/**
 * The main difference between AbstractAgent and AbstractObservingAgent is that
 * this one has a world to observe. It's a next step towards embodied agent.
 * 
 * @author Jimmy
 * @param WorldView
 *            class of the worldview the agent is working with
 */
@AgentScoped
public abstract class AbstractObservingAgent<WORLD_VIEW extends IStartableWorldView>
        extends AbstractAgent {

    /**
     * Instance of the world view - basic agent's internal representation of the
     * world.
     * <p>
     * <p>
     * Accessible via getWorldView().
     */
    private WORLD_VIEW worldView;

    @Inject
    public AbstractObservingAgent(AgentLogger logger, WORLD_VIEW worldView) {
        super(logger);
        this.worldView = worldView;
    }

    /**
     * Returns abstraction for the agent's world. That can be anything the range
     * is broad ... from chess board to the UT2004 3D environment. <BR>
     * <BR>
     * The implementation may be different as the user needs.
     *
     * @return
     */
    protected WORLD_VIEW getWorldView() {
        return worldView;
    }

    @Override
    public void start() throws AgentException {
        try {
            worldView.start();
        } catch (PogamutException ex) {
            throw new AgentException("Exception occured during world view startup.", ex, getLogger().platform());
        }
    }

    @Override
    public void kill() {
        worldView.kill();
    }

    @Override
    public void stop() {
        worldView.stop();
    }
    
}
