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

package sdsimulator.runnable;
import sdsimulator.runnable.expresiones.ExpresionLogica;
import myuml.*;

/**
 *
 * @author Miguel Herreros
 */
public class FrameLoopEjecutable extends FrameEjecutable{
    private ExpresionLogica guarda;
    private ExpresionLogica repeat;
    private boolean esperando;
    private int     iteracion;
    
    
    public FrameLoopEjecutable(MyFrame myFrame, VectorOrdenado eventos, ContextoEjecucion contexto, AsincronosPendientes asincronos){
        super(myFrame,eventos,contexto,asincronos);
        
        try{
            guarda=new ExpresionLogica(myFrame.getGuard(), myFrame.getVariablesGuarda(), contexto);/*ExpresionLogica(myFrame.getGuard(), contexto);*/
            repeat=new ExpresionLogica(myFrame.getRepeat(), myFrame.getVariablesRepeat(), contexto);/*ExpresionLogica(myFrame.getRepeat(), contexto);*/
        } catch(Exception e){
            System.out.println(e.getMessage());
        }
        
        esperando         = false;
        iteracion         = 0;
    }
    
    //..........................................................................
    @Override
    public ResultadoEjecucion run(){
        return runStep();
    }
    
    //..........................................................................
    /** Vamos a redefinir el comportamiento cuando empezamos y cuando detectemos
     * el final.
     */
    @Override
    public ResultadoEjecucion runStep(){
        switch (indiceEjecucion){
            case -1: return detectadoComienzo();
            default: esperando=false;
                     ResultadoEjecucion resultado = super.runStep();
                     if (terminado){
                         procesarRepeat();
                         textoRepeat(resultado);
                     }
                     return resultado;
        }
    }
    
    //..........................................................................
    @Override 
    protected ResultadoEjecucion detectadoComienzo(){
        ResultadoEjecucion retorno = new ResultadoEjecucion();
        retorno.x=getX();
        retorno.y=getY();
                          
        if (!esperando) //la primera vez en rojo
            myFrame.setCol(sdsimulator.Main.EN_CURSO);
                     
        procesarGuarda();
        textoFrame(retorno);
        textoGuarda(retorno);
        
        return retorno;    
    }
    
    //..........................................................................
    /**Prepara al frame para su ejecución, en función del resultado devuelto al 
     * evaluar la guarda. Si no hay guarda, entra a ejecutarlo. En otro caso, 
     * evalúa la guarda para comprobar si se debe ejecutar el contenido del bu-
     * cle o no.
     */
    private void procesarGuarda(){
        boolean resultadoGuarda=true;
        if (!guarda.isEmpty()) resultadoGuarda=guarda.evaluar();
        
        if (guarda.isEmpty() || resultadoGuarda){
            activarTodos(); //En realidad sólo activa uno (el único)
            indiceEjecucion++;
            esperando = false;
        }
        else if(!myFrame.getBlock()){
            anularTodos(); //La guarda no se cumple, pero no es bloqueante.
            indiceEjecucion++;
            esperando = false;
        }
        else 
            esperando = true;    
    }
    
    //..........................................................................
    /**Prepara al frame para su repetición. Si no hay expresión repeat, el bucle
     * no se repite más veces (recordar que se ejecutará al menos una vez). 
     * En otro caso, lo repite si el resultado de evaluar la expresión es true, 
     * cuando sea false, el bucle terminará de ejecutarse.
     */
    private void procesarRepeat(){
        boolean resultadoRepeat=false;
        if (!repeat.isEmpty()) 
            resultadoRepeat=repeat.evaluar();
        
        if (resultadoRepeat){
            for (int i=0; i<componentesEjecutables.size();i++){
                ComponenteEjecutable componente = (ComponenteEjecutable)(componentesEjecutables.get(i));
                componente.reset();
            }
            indiceEjecucion=-1;
            esperando = false;
            terminado = false;
            iteracion++;
        }  
    }
    
    //..........................................................................
    /** Coloca el texto correspondiente a la detección del frame en el resultado
     *  a devolver.
     * @param retorno
     */
    private void textoFrame(ResultadoEjecucion retorno){
        if (!esperando) //es la primera vez (se cumpla o no la guarda)
            retorno.traza = bundle.getString("FRAME");
        else
            retorno.traza = bundle.getString("FRAME_BLOQUEADO");
            
        retorno.traza+= myFrame.getName();
        retorno.traza+= bundle.getString("FRAME1");
        retorno.traza+= myFrame.getID();
        retorno.traza+= bundle.getString("FRAME_LOOP") + iteracion;
        retorno.traza+= bundle.getString("FRAME_LOOP1");
    }
    
    //..........................................................................
    /** Coloca el texto correspondiente a la evaluación de la guarda del frame 
     *  encontrada en la traza.
     * @param retorno
     */
    private void textoGuarda(ResultadoEjecucion retorno){
        if (!guarda.isEmpty()){
            if (myFrame.getBlock())
                retorno.traza+= bundle.getString("GUARDA_BLOQUEANTE");
            else
                retorno.traza+= bundle.getString("GUARDA_NO_BLOQUEANTE");    
                retorno.traza+= guarda.toString();
                retorno.traza+= bundle.getString("GUARDA1");
        }
    }

    //..........................................................................
    /** Coloca el texto correspondiente a la evaluación del repeat del frame 
     *  para la traza.
     * @param retorno
     */
    private void textoRepeat(ResultadoEjecucion retorno){
        if (!repeat.isEmpty()){
            retorno.traza+= bundle.getString("REPEAT");    
            retorno.traza+= repeat.toString();
            retorno.traza+= bundle.getString("REPEAT1");
        }
    }
    
    //..........................................................................
    @Override 
    public void reset(){
        super.reset();
        esperando = false;
        iteracion = 0;
    }
}
