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

package sdsimulator.runnable;
import myuml.*;
import java.util.*;

/**
 *
 * @author Miguel Herreros
 */
public class MensajeEjecutable implements ComponenteEjecutable{
    //Referencia a su homólogo dibujable.
    private MyMessage mensaje;  
    //Referencias a su actor/objeto dibujables.
    private MyObjects entidadDesde, entidadHasta;
    //Este vector contiene todas las variables en nuestro propio formato (dise-
    //ñado para facilitar la ejecución)
    private Vector expresiones= new Vector(30,50);
    //Número de pasos que se consumen en la ejecución de un objeto de esta clase.
    private boolean enviado;
    private boolean llegado; //para los asíncronos.
    private boolean permitido;
    private int bloque;       //Si está contenido en un frame, contiene el número 
                             //del bloque al que pertenece.
    private java.util.ResourceBundle bundle;
    
    public MensajeEjecutable(MyMessage myMessage, ContextoEjecucion contexto){
        mensaje   = myMessage;
        enviado   = false;
        llegado   = false;
        permitido = true;
        bloque    = -1;
        
        ArrayList updates;
        AsignacionValor expresion;
        String idSource = myMessage.getSource();
        String idDest   = myMessage.getDest();
        entidadDesde = contexto.getEntidades().getByID(idSource); 
        entidadHasta = contexto.getEntidades().getByID(idDest);
        
        updates=myMessage.getUpdates();
        
        for (int i=0; i<updates.size();i++){
            expresion= new AsignacionValor(updates.get(i),contexto);
            expresiones.add(expresion);
        }
        
        bundle = java.util.ResourceBundle.getBundle("sdsimulator/resources/runnable");
    }
    
    public ResultadoEjecucion run(){                
        if (mensaje.getAsin())
            return RunAsincrono();
        else
            return RunSincrono();
    }
    
    private ResultadoEjecucion RunSincrono(){
        ResultadoEjecucion retorno = new ResultadoEjecucion();
        retorno.x = mensaje.getXY().getX();
        retorno.y = mensaje.getXY().getY();
        retorno.traza=trazaSincrono();
        
        enviado   = true;
        llegado   = true;
        
        mensaje.setCol(sdsimulator.Main.EN_CURSO);
        
        for (int i=0; i<expresiones.size();i++)
            ((AsignacionValor)expresiones.get(i)).run();
        
        return retorno;
    }
    
    private ResultadoEjecucion RunAsincrono(){
        ResultadoEjecucion retorno = new ResultadoEjecucion();
        retorno.x = mensaje.getXY().getX();
        retorno.y = mensaje.getXY().getY();
        retorno.traza=trazaAsincronoEnviado();
        
        enviado   = true;
        llegado   = false;
        
        mensaje.setCol(sdsimulator.Main.EN_CURSO);
       
        return retorno;
    }
            
    public String LlegaAsincrono(int pasoEnvio){
        String retorno;
        retorno=trazaAsincronoLlegado(pasoEnvio);
        
        llegado    = true;
        
        mensaje.setCol(sdsimulator.Main.COMPLETO);
        
        for (int i=0; i<expresiones.size();i++)
            ((AsignacionValor)expresiones.get(i)).run();
        
        return retorno;
    }
            
    
    public void postRun(){
        if (!llegado)
            mensaje.setCol(sdsimulator.Main.PENDIENTE);
        else
            mensaje.setCol(sdsimulator.Main.COMPLETO);
    }
    
    public boolean completado(){
        return enviado;
    }
    
    public void reset(){
        enviado   = false;
        llegado   = false;
        permitido = true;
        
        mensaje.setCol(sdsimulator.Main.NUEVO);
        //Ahora deberíamos devolver todas las variables modificadas a su valor 
        //original, pero lo que vamos a hacer es, al final, restaurar el estado
        //completo (todas las variables) a sus valores originales.
    }
    
    public boolean getAsin(){
        return mensaje.getAsin();    
    }
    
    public int getX(){
        return mensaje.getXY().getX();    
    }
    
    public int getY(){
        return mensaje.getXY().getY();    
    }
     
    public void setPermitido(boolean permitido){
        this.permitido = permitido;
    }
    
    public boolean getPermitido(){
        return this.permitido;
    }
    
    public void setBloque(int bloque){
       this.bloque = bloque;    
    }
    
    public int getBloque(){
        return this.bloque;
    }
    
    private String trazaSincrono(){
        String retorno = bundle.getString("MENSAJE")  + mensaje.getName()      +
                         bundle.getString("MENSAJE1") + entidadDesde.getName() +
                         bundle.getString("MENSAJE2") + entidadHasta.getName() +
                         bundle.getString("MENSAJE3");
                
        for (int i=0; i<expresiones.size();i++)
            retorno+=((AsignacionValor)expresiones.get(i)).toString();
        
        return retorno;
    }
    
    private String trazaAsincronoEnviado(){
        String retorno = bundle.getString("AMENSAJE") + mensaje.getName()      +
                         bundle.getString("MENSAJE1") + entidadDesde.getName() +
                         bundle.getString("MENSAJE2") + entidadHasta.getName() +
                         bundle.getString("MENSAJE3");
                
        return retorno;
    }
    
    private String trazaAsincronoLlegado(int pasoEnvio){
        String retorno = bundle.getString("AMENSAJE")  + mensaje.getName()      +
                         bundle.getString("AMENSAJE1") + entidadDesde.getName() +
                         bundle.getString("AMENSAJE2")  + entidadHasta.getName() +
                         bundle.getString("ENVIADO_EN") + pasoEnvio + bundle.getString("ENVIADO_EN1"); 
                
        for (int i=0; i<expresiones.size();i++)
            retorno+=((AsignacionValor)expresiones.get(i)).toString();
        
        return retorno;
    }
}
