package modelling;

import sema.Area;
import sema.Agent.Action;
import sema.Agent;
import modelling.Satisfactor;
import sema.World;

/**
 * A generalist Action which try to satisfy a satisfator using an action.
 * When it has succed, it stops the action and starts the futur before ending.
 * If paused, it also pauses its changFor action.
 *
 * Every given action can be null, it means it does nothing.
 */

public class ActToSatisfaction extends sema.Agent.Action {
    //
    private Action act;
    private Satisfactor endCondition;
    private Action succes;
    private Action echec;
    private float verifyDelay;
    
    /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Satisfactor endCondition) {
	this(a,null,endCondition,a.getDelay(),null,null);
    }
     /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Satisfactor endCondition, float verifyDelay) {
	this(a,null,endCondition,verifyDelay,null,null);
    }
     /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition) {
	this(a,action,endCondition,a.getDelay(),null,null);
    }
    /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition, float verifyDelay) {
	this(a,action,endCondition,verifyDelay,null,null);
    }
     /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition, Action succes) {
	this(a,action,endCondition,a.getDelay(),succes,null);
    }
     /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition, float verifyDelay, Action succes) {
	this(a,action,endCondition,verifyDelay,succes,null);
    }
     /**
     * 
     * @see #ActToSatisfaction(sema.Agent a, sema.Agent.Action action, modelling.Satisfactor endCondition, float verifyDelay, sema.Agent.Action succes, sema.Agent.Action failure)
     */
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition, Action succes, Action failure) {
	this(a,action,endCondition,a.getDelay(),succes,failure);
    }
    
    
    
    /**
     * Constructs the action.
     * @param a the agent to which this action will register.
     * @param action the action to execute when waiting for the endCondition to be satisfiyed.
     * @param endCondition the condition saying whether we reach our goal
     * @param verifyDelay the delay of refresshing of the stat of the condition : every verifydelay secondes we call the isSatisfied of the endCondition.
     * @param succes the action to execute when we succed to satisfy the endCondition
     * @param failure the action to execute when we don't succed to satisfy the endCondition
     */
    public ActToSatisfaction(sema.Agent a, Action action, Satisfactor endCondition, float verifyDelay, Action succes, Action failure) {
	a.super();
	this.act = action;
	this.echec = failure;
	this.endCondition = endCondition;
	this.verifyDelay = verifyDelay;
	this.succes = succes;
    }
    
    public float firstStep() {
	if (!endCondition.isSatisfying()) {
	    if(act!=null) act.start(verifyDelay);
	    return 0;
	} else {
	    if (act!=null) act.stop();
	    return -1;
	}
    }
    
    public float step() { //we try to
	if(!endCondition.isSatisfying()) {
	    if(act!=null) {
		if(act.isPaused()) act.resume(); //if the act is in pause we resume it
		if(act.isDisabled()) this.stop(); //we can't continuate
	    }
	    return verifyDelay;
	} else  {
	    if(act!=null) act.stop();
	    return -1;
	}
    }
    
    public void whenPaused() { //when paused we pause the search
	if (act!=null) act.pause();
    }
    public void whenEnd() {
	
    }
    
    public void close() { // we stop the search action and let if started the succesfor
	if (endCondition.isSatisfying()) {
	    if(succes != null) succes.start();
	} else {
	    if(echec != null) echec.start();
	}
	if (act!=null) act.stop();
    }
    
    
}
