/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package sdsimulator.runnable;
import java.util.Vector;
import myuml.*;
/**
 *
 * @author Miguel Herreros
 */
public abstract class SecuenciaComponentesEjecutables {
    protected java.util.ResourceBundle  bundle;
    protected ContextoEjecucion contexto;
    protected AsincronosPendientes asincronos; //Viene como parámetro. Una vez que un frame envía un mensaje asíncrono, lo deja aquí.
    protected int indiceEjecucion; //Contador para la ejecución.
    protected boolean terminado;
    
    //Este vector contiene todos los elementos ejecutables contenidos dentro de la secuencia.
    protected Vector componentesEjecutables;
        
    //..........................................................................
    public SecuenciaComponentesEjecutables(ContextoEjecucion contexto, AsincronosPendientes asincronos){
        bundle = java.util.ResourceBundle.getBundle("sdsimulator/resources/runnable");
        this.contexto          = contexto;
        this.asincronos        = asincronos;
        indiceEjecucion        = -1;
        terminado              = false;
        componentesEjecutables = new Vector(50,10);
    }
    
    //..........................................................................
    /** Aparentemente, bastaría con invocar a este método abstracto al final del 
     *  constructor. sin embargo, es mejor invocarla en el constructor del descen-
     *  diente. En ocasiones, se daba que al implementar este método, se usaban 
     *  datos específicos del descendiente y como el constructor de la superclase
     *  tiene que ser siempre la primera sentencia, éstos campos todavía no estaban
     *  inicializados.
     * 
     * @param eventos
     * @param contexto
     */
    protected abstract void agregarComponentesEjecutables(VectorOrdenado eventos, ContextoEjecucion contexto);
    
    //.........................................................................
    protected void agregarFrame(MyFrame myFrame, VectorOrdenado eventos, ContextoEjecucion contexto, AsincronosPendientes asincronos){
        String tipo=myFrame.getName();
         
        if      (tipo.compareTo("par")==0)
            componentesEjecutables.add(new FrameParEjecutable(myFrame, eventos, contexto, asincronos));
         
        else if (tipo.compareTo("alt")==0)
            componentesEjecutables.add(new FrameAltEjecutable(myFrame, eventos, contexto, asincronos));
         
        else if(tipo.compareTo("loop")==0)
            componentesEjecutables.add(new FrameLoopEjecutable(myFrame, eventos, contexto, asincronos));
         
        else if(tipo.compareTo("alt_else")==0)
            componentesEjecutables.add(new FrameAltElseEjecutable(myFrame, eventos, contexto, asincronos));
         
        else //Opt
            componentesEjecutables.add(new FrameOptEjecutable(myFrame, eventos, contexto, asincronos));    
     }
    
    //..........................................................................
    public ResultadoEjecucion runStep(){
         switch (indiceEjecucion){
             case -1: return detectadoComienzo();
             default: return restoPasos();
         }
    }
    //.........................................................................
    protected abstract ResultadoEjecucion detectadoComienzo();
    
    //.........................................................................
    protected abstract ResultadoEjecucion restoPasos();
    
    //.........................................................................
    protected abstract ResultadoEjecucion detectadoFinal();
    
    //.........................................................................
    public boolean completado(){
        return terminado;
    }
    
    //..........................................................................
    public void reset(){
        indiceEjecucion = -1;
        terminado       = false;
        
        for (int i=0;i<componentesEjecutables.size();i++){
            ((ComponenteEjecutable)componentesEjecutables.get(i)).reset();
        }
     }
}
