package cl.jtv;
/*
 * CondicionEnlace.java
 *
 * Created on 19 de agosto de 2002, 08:55 PM
 */

/**
 *
 * @author  Administrador
 * @version 
 */
import java.util.*;
import java.awt.*;
import java.awt.geom.Rectangle2D;
import java.awt.font.FontRenderContext;


public class CondicionEnlace {

    /** Creates new Class */
    public Hashtable operandosIzquierdo;
    public Hashtable operandosDerecho;
    public Hashtable operandosNots;
    private String operandos;
    
    private boolean not;
    public int x0,y0;
    
    public CondicionEnlace(){
        
        operandosIzquierdo = new Hashtable();
        operandosDerecho = new Hashtable();
        operandosNots = new Hashtable();
        not = false;
    }
    
    public CondicionEnlace(boolean _not){
        
        operandosIzquierdo = new Hashtable();
        operandosDerecho = new Hashtable();
        operandosNots = new Hashtable();
        not = _not;
    }
    
     public void agregaOperandoNot(Boolean not,int newIndexTape){
        
        Integer indexTape = new Integer(newIndexTape);
        
        if(this.operandosNots.containsKey(indexTape))
            this.operandosNots.remove(indexTape);
        
        this.operandosNots.put(indexTape,not);    
    }
    
    public void agregaOperandoIzquierdo(String operando,int newIndexTape){
        
        Integer indexTape = new Integer(newIndexTape);
        
        if(this.operandosIzquierdo.containsKey(indexTape))
            this.operandosIzquierdo.remove(indexTape);
        
        this.operandosIzquierdo.put(indexTape,operando);    
    }
    
    public void eliminaOperandoIzquierdo(int newIndexTape){
        
        Integer indexTape = new Integer(newIndexTape);
        operandosIzquierdo.remove(indexTape);
    }
    
    public void agregaOperandoDerecho(String operando,int newIndexTape){
        
        Vector operandosCinta=null;
        Integer indexTape = new Integer(newIndexTape);
        
        if(!this.operandosDerecho.containsKey(indexTape)){
            operandosCinta = new Vector();
            this.operandosDerecho.put(indexTape,operandosCinta);
        }
        
        operandosCinta = (Vector)this.operandosDerecho.get(indexTape);
        if(!operandosCinta.contains(operando)) operandosCinta.add(operando);
        
    }
    
    public boolean contieneOperandoDerecho(String operando,int newIndexTape){
        
        Integer indexTape = new Integer(newIndexTape);
        return this.operandosDerecho.containsKey(indexTape) && ((Vector)this.operandosDerecho.get(indexTape)).contains(operando);
    }
    
    public void eliminaOperandoDerecho(String operando,int newIndexTape){
        
        Integer indexTape = new Integer(newIndexTape);
        Vector operandosCinta = (Vector)this.operandosDerecho.get(indexTape);
        
        if(operandosCinta!=null){
            operandosCinta.remove(operando);
            if(operandosCinta.isEmpty()) this.operandosDerecho.remove(indexTape);
        }
    }
    
    public boolean isNot(Integer indexCinta){
        
        return ((Boolean)this.operandosNots.get(indexCinta)).booleanValue();
              
    }
    
    public boolean getNot(){
        
        return not;
    }
    
    public void setNot(boolean _not){
        
        not = _not;
    }
    
    public void limpiarOperandosDerecho(){
        this.operandosDerecho.clear();
    }
    
    public void limpiarOperandosIzquierdo(){
        this.operandosIzquierdo.clear();
    }
    
    public ResultadoEvaluacion evaluar(Cinta[] arrayOfTapes,DiccionarioMetavalores dicMetavalores) throws NonSetException{
        int I;
        ResultadoEvaluacion out = new ResultadoEvaluacion(true,this);
        Enumeration en = this.operandosDerecho.keys();
        Vector<Boolean> resultadosBooleanos = new Vector<Boolean>();
        for(I=0;I<this.operandosDerecho.size();I++)
            resultadosBooleanos.add(Boolean.FALSE);
        I=0;
        while(en.hasMoreElements()){
            Integer indexCinta = (Integer)en.nextElement();
            int indexCintaInt = indexCinta.intValue();
            Simbolo valorCinta = arrayOfTapes[indexCintaInt].leer();
            Vector operandosCinta = (Vector)this.operandosDerecho.get(indexCinta);
            //System.out.println("indexCinta="+indexCinta);
            int counterNots=0;
            for(int i=0;i<operandosCinta.size();i++){
                String operandoCinta = (String)operandosCinta.get(i);
                //System.out.println("operandoCinta="+operandoCinta);
                if((!CondicionEnlace.isNombreSimbolo(operandoCinta)) && dicMetavalores.hasMetavalor(operandoCinta)){
                    //System.out.println("OK 1");
                    Metavalor metavalor = dicMetavalores.getMetavalor(operandoCinta);
                    //System.out.println(metavalor.getNombre());
                    if(metavalor.getValor()==valorCinta){
                        out.metavaloresResultado.put(indexCinta,metavalor);
                        resultadosBooleanos.set(I,this.isNot(indexCinta)?Boolean.FALSE:Boolean.TRUE);
                        //resultadosBooleanos.set(I,Boolean.TRUE);
                        /*if(!this.isNot(indexCinta)){
                            resultadosBooleanos.set(I,Boolean.TRUE);
                            break;
                        }
                        else{
                            
                            
                            
                        }*/
                        break;
                    }
                    else{
                        out.metavaloresResultado.put(indexCinta,metavalor);
                        //resultadosBooleanos.set(I,this.isNot(indexCinta)?Boolean.TRUE:Boolean.FALSE);
                        //resultadosBooleanos.set(I,Boolean.TRUE);
                        if(!this.isNot(indexCinta)){
                            resultadosBooleanos.set(I,Boolean.FALSE);
                            //break;
                            continue;
                        }
                        else{
                            counterNots++;
                            continue;
                        }
                    }
                }
                else if((!CondicionEnlace.isNombreSimbolo(operandoCinta)) && !dicMetavalores.hasMetavalor(operandoCinta)){
                    //System.out.println("OK 1.5");
                    out.setError(true);
                    out.setStrError(operandoCinta+"=INDEFINIDO");
                    return out;
                    //throw new NonSetException();
                }
                else if(operandoCinta.equals(valorCinta.getNombre())){
                    //System.out.println("OK 2");
                    out.metavaloresResultado.put(indexCinta,Simbolo.getSimbolo(operandoCinta));
                    resultadosBooleanos.set(I,this.isNot(indexCinta)?Boolean.FALSE:Boolean.TRUE);
                    //System.out.println("valorCinta.getNombre()="+valorCinta.getNombre());
                    //if(!this.isNot(indexCinta))
                    break;                   
                }
                else if((!operandoCinta.equals(valorCinta.getNombre()))){
                    //System.out.println("OK 3");
                    out.metavaloresResultado.put(indexCinta,valorCinta);
                    //resultadosBooleanos.set(I,this.isNot(indexCinta)?Boolean.TRUE:Boolean.FALSE);
                    //System.out.println("valorCinta.getNombre()="+valorCinta.getNombre());
                    //if(!this.isNot(indexCinta))
                    //break;
                    
                    if(!this.isNot(indexCinta)){
                         resultadosBooleanos.set(I,Boolean.FALSE);
                         //break;
                         continue;
                    }
                    else{
                         counterNots++;
                         continue;
                    }
                }      
            }
            if(this.isNot(indexCinta) && counterNots==operandosCinta.size()) resultadosBooleanos.set(I,Boolean.TRUE);
            I++;   
        }
        //out = true;
        for(int i=0;i<resultadosBooleanos.size();i++){
            if(!((Boolean)resultadosBooleanos.get(i)).booleanValue()){
                //out = false;
                out.setResultado(false);
                break;
            }
        }     
        //if(not) out=!out;
        //if(not) out.setResultado(!out.isResultado());
        return out;
    }
    
    public String asignar(Metavalor metavalor,Integer indexCinta,DiccionarioMetavalores dicMetavalores) throws NonSetException{
        
        String out="";
        if(this.operandosIzquierdo.containsKey(indexCinta)){
            String nombreVariable = (String) this.operandosIzquierdo.get(indexCinta);
            Metavalor variable = dicMetavalores.getMetavalor(nombreVariable);
            if(variable==null){
                variable = new Variable(nombreVariable);
                dicMetavalores.insertaVariable((Variable)variable);
            }
            variable.setValor(metavalor);
            out = "[" + variable.getAsignacion()+ ";" + (indexCinta.intValue()+1) + "]";
        }
        else
            out = "[" + metavalor.getAsignacion()+ ";" + (indexCinta.intValue()+1) + "]";
       
        return out;
    }
    
    /*public boolean evaluar(char valor){
     
        Enumeration en = this.operandosDerecho.elements();
        boolean out;
        
        out = false;
        
        if(this.operandosDerecho.isEmpty()) out = true;
        
        while(en.hasMoreElements()){
            
            Object obj = en.nextElement();
            
            if(obj instanceof Character){
                if(valor==((Character)obj).charValue()) out = true;
            }
            
            if(obj instanceof CaracterSigma_1){
                
                if(valor==((CaracterSigma_1)obj).getValor()) out = true;
            }
            
        }
        
        if(not)
            return !out;
        else
            return out;
    }*/
    
    public void dibujar(Graphics g){
        
        //operandos="";
        g.setFont(Maquina.FONT_TRI14);
        //Enumeration en = null;
        Set en = null;
        Enumeration en2 = null;
        if(this.operandosDerecho.size()>this.operandosIzquierdo.size()){
            en = this.operandosDerecho.keySet();
            en2 = this.operandosIzquierdo.keys();
        }
        else{
            en = this.operandosIzquierdo.keySet();
            en2 = this.operandosDerecho.keys();
        }
        
        java.util.List list = new java.util.ArrayList(en);
        while(en2.hasMoreElements()){
            Object obj = en2.nextElement();
            if(!list.contains(obj)) list.add(obj);
        }
        if(list.size()==0) return;
        java.util.Collections.sort(list);      
        java.util.Iterator iter = list.iterator();
        
        //while(en.hasMoreElements()){
        while(iter.hasNext()){
            //Integer indexCinta = (Integer)en.nextElement();
            Integer indexCinta = (Integer)iter.next();
            
            String operandosCinta = "";
            if(this.operandosDerecho.containsKey(indexCinta))
                operandosCinta = ((Vector)this.operandosDerecho.get(indexCinta)).toString();
            if(operandosCinta.length()!=0)
                operandosCinta = operandosCinta.substring(1,operandosCinta.length()-1);
            if(this.operandosIzquierdo.containsKey(indexCinta))
                operandosCinta = (String)this.operandosIzquierdo.get(indexCinta) + " = " + operandosCinta;
            operandosCinta = "["+operandosCinta;
            //operandosCinta = operandosCinta + ";" + (indexCinta.intValue()+1) + "]";
            operandosCinta = operandosCinta + (Maquina.displayIndex?(";" + (indexCinta.intValue()+1)):"") + "]";
            java.awt.geom.Rectangle2D rect = Maquina.FONT_TRI14.getStringBounds(operandosCinta,new FontRenderContext(Maquina.FONT_TRI14.getTransform(),true,true));
            g.drawString(operandosCinta,x0,y0);
            if(isNot(indexCinta)) g.drawLine(x0,y0-(int) rect.getHeight()+4,x0+(int) rect.getWidth(),y0-(int) rect.getHeight()+4);
            x0+=(int) rect.getWidth()+1;
            //operandos+=operandosCinta;
        }
        
        /*g.setFont(Maquina.FONT_TRI14);
        g.drawString(operandos,x0,y0);
        if(not){
            Rectangle2D rect = Maquina.FONT_TRI14.getStringBounds(operandos,new FontRenderContext(Maquina.FONT_TRP13.getTransform(),true,true));
            g.drawLine(x0,y0-(int) rect.getHeight()+4,x0+(int) rect.getWidth(),y0-(int) rect.getHeight()+4);
        }*/
        
        /*g.setFont(Maquina.FONT_TRI14);
        g.drawString(operandos,x0,y0);
        if(not){
            Rectangle2D rect = Maquina.FONT_TRI14.getStringBounds(operandos,new FontRenderContext(Maquina.FONT_TRP13.getTransform(),true,true));
            g.drawLine(x0,y0-(int) rect.getHeight()+4,x0+(int) rect.getWidth(),y0-(int) rect.getHeight()+4);
        }*/
    }
    
    public static boolean isNombreSimbolo(String nombreSimbolo){
        if(nombreSimbolo==null) return false;
        if(nombreSimbolo.length()!=1) return false;
        char c = nombreSimbolo.charAt(0);
        return ('a'<=c && c<='z')||('0'<=c && c<='9')||c=='#';
    }
    
    public static boolean isNombreVariable(String nombreVariable){
        
        return (!CondicionEnlace.isNombreParametro(nombreVariable)) && (!CondicionEnlace.isNombreSimbolo(nombreVariable));
    }
    
    public static boolean isNombreParametro(String nombreParametro){
        
        if(nombreParametro.length()!=1) return false;
        char c = nombreParametro.charAt(0);
        return ('A'<=c && c<='Z');
    }
    
    public void setOperandos(){
        
        operandos="";
        Enumeration en = null;
        
        if(this.operandosDerecho.size()>this.operandosIzquierdo.size())
            en = this.operandosDerecho.keys();
        else
            en = this.operandosIzquierdo.keys();
        
        while(en.hasMoreElements()){
            Integer indexCinta = (Integer)en.nextElement();
            
            String operandosCinta = "";
            if(this.operandosDerecho.containsKey(indexCinta))
                operandosCinta = ((Vector)this.operandosDerecho.get(indexCinta)).toString();
            if(operandosCinta.length()!=0)
                operandosCinta = operandosCinta.substring(1,operandosCinta.length()-1);
            if(this.operandosIzquierdo.containsKey(indexCinta))
                operandosCinta = (String)this.operandosIzquierdo.get(indexCinta) + " = " + operandosCinta;
            operandosCinta = "["+operandosCinta;
            operandosCinta = operandosCinta + (Maquina.displayIndex?(";" + (indexCinta.intValue()+1)):"") + "]";
            operandos+=operandosCinta;
        }     
    }
    
    public String getOperandos(){
        
        return operandos;
    }
    
    public Object clone(){
        
        CondicionEnlace ce = new CondicionEnlace();
        ce.operandosDerecho = (Hashtable)this.operandosDerecho.clone();
        ce.operandosIzquierdo = (Hashtable)this.operandosIzquierdo.clone();
        ce.operandosNots = (Hashtable)this.operandosNots.clone();
        ce.setOperandos();
        return ce;
        
    }
    
    public Rectangle2D getStringBounds(){
        
        return Maquina.FONT_TRI14.getStringBounds(operandos,new FontRenderContext(Maquina.FONT_TRP13.getTransform(),true,true));
    }
    /*    Object[] arrayOperandos = this.operandosDerecho.toArray();
        String stringOperandos = "";
        
        if(arrayOperandos.length==0) return;
         
        for(int i=0;i<arrayOperandos.length;i++){
            
            Object obj = arrayOperandos[i];
            
            if(obj instanceof Character){
               stringOperandos+=((Character)obj).charValue();
            }
            
            if(obj instanceof CaracterSigma_1){
                stringOperandos+=((CaracterSigma_1)obj).getValor();
            }
            
            if(arrayOperandos.length-i>1)
                stringOperandos+=",";
        }
        
        g.setFont(Maquina.FONT_TRP13);
        g.drawString(stringOperandos,x0,y0);
        
        if(not){
            Rectangle2D rect = Maquina.FONT_TRP13.getStringBounds(stringOperandos,new FontRenderContext(Maquina.FONT_TRP13.getTransform(),true,true));
            g.drawLine(x0,y0-(int) rect.getHeight()+4,x0+(int) rect.getWidth(),y0-(int) rect.getHeight()+4);
        }
        
    }*/
    
   /* public boolean isEmpty(){
        
        return this.operandosDerecho.isEmpty();
    }*/

}
