package cl.jtv;
/*
 * Clipboard.java
 *
 * Created on 25 de febrero de 2003, 05:24 PM
 */

/**
 *
 * @author  Administrador
 * @version 
 */
import java.util.*;
import javax.swing.*;
import java.awt.*;
import java.io.*;

public class Clipboard {
    
    public static int x0,y0,x1,y1;
    
    private static Rectangle rectClipboard;
    private static DaemonClipboard daemonClipboard;
    private static Thread threadClipboard;
    private static Vector2 clipboardVector;
    private static Hashtable clipboardHashtable;
    private static boolean enabled;
    private static boolean changeInicial;
    private static boolean message;
    private static Integer monitor;
    private static int state;
    
    public static Maquina clipboardMachine;
    
    public static final int STATE_NOTHING=0;
    public static final int STATE_CUT=1;
    public static final int STATE_COPY=2;
    public static final int STATE_PASTE=3;
    public static final int STATE_DELETE=4;
    
    public static final int VALID_SIZE_CLIPBOARD = 4;
    /** Creates new Clipboard */
    public Clipboard() {
        
    }
    
    static{
        
        Clipboard.clipboardVector = new Vector2();
        Clipboard.clipboardVector.setNombreLargo("CLIPBOARD");
        Clipboard.clipboardVector.setPrincipal(true);
        Clipboard.clipboardVector.setMonocinta(false);
        Clipboard.rectClipboard = new Rectangle();
        Clipboard.clipboardHashtable = new Hashtable();
        Clipboard.clipboardMachine = null;
        enabled = false;
        message = false;
        state = Clipboard.STATE_NOTHING;
        monitor = new Integer(0);
    }
    
    public static void drawClipboard(Graphics g){
        
        if(!enabled) return;
        g.setColor(Color.magenta);
        g.drawRect(Math.min(x0,x1),Math.min(y0,y1),Math.abs(x1-x0),Math.abs(y1-y0));
        g.setColor(Color.black);
        
    }
    
    public static boolean isValidClipboard(){
        return (Math.abs(x1-x0)>=VALID_SIZE_CLIPBOARD || Math.abs(y1-y0)>=VALID_SIZE_CLIPBOARD);
    }
    
    private static void fillClipboard(Vector vector2){
        
        Clipboard.rectClipboard.setBounds(Math.min(x0,x1),Math.min(y0,y1),Math.abs(x1-x0),Math.abs(y1-y0));
        Enumeration en = vector2.elements();
        Clipboard.clipboardHashtable.clear();
        
        while(en.hasMoreElements()){
            Maquina maquina = (Maquina)en.nextElement();            
            //if(!(maquina instanceof Enlace) && (rectClipboard.contains(maquina.getBoundRectangle())||maquina.getBoundRectangle().contains(rectClipboard)))
            if(!(maquina instanceof Enlace) && rectClipboard.intersects(maquina.getBoundRectangle())){  
                Clipboard.clipboardVector.add(maquina);
                Clipboard.clipboardHashtable.put(new Integer(maquina.idMaquina),maquina);                
            }
            
        }
        
        en = null;
        en = vector2.elements();
        while(en.hasMoreElements()){
            Maquina maquina = (Maquina)en.nextElement();  
            if((maquina instanceof Enlace) && Clipboard.rectClipboard.intersects(maquina.previa.getBoundRectangle()) && Clipboard.rectClipboard.intersects(maquina.proxima.getBoundRectangle())){
                Clipboard.clipboardVector.add(maquina);               
            }
        }
        
        if(!changeInicial && Clipboard.clipboardVector.size()!=0){
            Clipboard.clipboardVector.inicial.setInicial(Clipboard.clipboardVector.inicial==((Vector2)vector2).inicial);             
            Clipboard.clipboardVector.inicial = null;
        }
                                             
    }
    
    public static void sendMessage(boolean message){
        
        
        Clipboard.daemonClipboard.sendMessage(message);
        
    }
    
    public static void setEnabledCutCopy(boolean enabled){
        
        Clipboard.daemonClipboard.jButtonCut.setEnabled(enabled);
        Clipboard.daemonClipboard.jButtonCopy.setEnabled(enabled);
        Clipboard.daemonClipboard.jMenuItemCut.setEnabled(enabled);
        Clipboard.daemonClipboard.jMenuItemCopy.setEnabled(enabled);
    }
    
    
    public static void reset(){
        
        state = Clipboard.STATE_NOTHING;
        Clipboard.sendMessage(false);
        Clipboard.setEnabled(false);
        Clipboard.clipboardVector.clear();
        Clipboard.clipboardHashtable.clear();
    }
    
    
    public static void cut(Vector vector2){
        if(state==Clipboard.STATE_COPY) {            
            return;
        }
        state = Clipboard.STATE_CUT;
        enabled = false;
        Clipboard.clipboardVector.clear();
        fillClipboard(vector2);
        Clipboard.changeInicial = false;
        
        ComandoCUT comandoCUT = new ComandoCUT(null,null);
        ComandoCUT comandoCUTInverse = new ComandoCUT(null,null);
        comandoCUT.setInverse(comandoCUTInverse);
        Comando.addComando2UR(comandoCUT);
        
        Enumeration en = Clipboard.clipboardVector.elements();
        while(en.hasMoreElements()){
                   Maquina maquina = (Maquina)en.nextElement();
                   if(!(maquina instanceof Enlace) && maquina.previa!=null &&!Clipboard.rectClipboard.intersects(maquina.previa.getBoundRectangle())){
                       ComandoSPRInv comandoSPRInv = new ComandoSPRInv(maquina,null);
                       comandoCUTInverse.addComando(comandoSPRInv);
                       ComandoSPR comandoSPR = new ComandoSPR(maquina,null);
                       comandoCUT.addComando(comandoSPR);
                       maquina.previa.proxima = null;
                       maquina.previa = null;
                       
                   }
                   if(!(maquina instanceof Enlace) && !(maquina.proxima instanceof EnlaceCompuesto) && maquina.proxima!=null && !Clipboard.rectClipboard.intersects(maquina.proxima.getBoundRectangle())){
                       ComandoSPXInv comandoSPXInv = new ComandoSPXInv(maquina,null);
                       comandoCUTInverse.addComando(comandoSPXInv);
                       ComandoSPX comandoSPX = new ComandoSPX(maquina,null);
                       comandoCUT.addComando(comandoSPX);
                       maquina.proxima.previa = null;
                       maquina.proxima = null;
                       
                   }
                   
                                      
                   ComandoRMV comandoRMV = new ComandoRMV(maquina,(Vector2)vector2);
                   comandoCUT.addComando(comandoRMV);
                   ComandoADD comandoADD = new ComandoADD(maquina,(Vector2)vector2);
                   comandoCUTInverse.addComando(comandoADD);
                   vector2.remove(maquina);
                   if(maquina.isInicial()){ 
                        ((Vector2)vector2).inicial = null;
                        maquina.setInicial(false);
                   }
               }
                
        en = null;
        en = ((Vector)vector2.clone()).elements();
        
        while(en.hasMoreElements()){
            Maquina maquina = (Maquina)en.nextElement();
            //if((clipboardVector.contains(enlace.previa)&&!clipboardVector.contains(enlace.proxima))||((!clipboardVector.contains(enlace.previa))&&clipboardVector.contains(enlace.proxima))){
            if(maquina instanceof Enlace){
                //if(!(!Clipboard.rectClipboard.intersects(maquina.previa.getBoundRectangle()) && !Clipboard.rectClipboard.intersects(maquina.proxima.getBoundRectangle()))){                
                Integer idPrevia = new Integer(maquina.previa.idMaquina);
                Integer idProxima = new Integer(maquina.proxima.idMaquina);                
                if(Clipboard.clipboardHashtable.containsKey(idPrevia) && !Clipboard.clipboardHashtable.containsKey(idProxima)){                    
                    ComandoEM comandoEM = new ComandoEM(maquina,(Vector2)vector2);
                    comandoCUT.addComando(comandoEM);
                    ComandoIE comandoIE = new ComandoIE(maquina,(Vector2)vector2);
                    comandoCUTInverse.addComando(comandoIE);
                    maquina.deleteMachine(vector2);                    
                }
                else if(Clipboard.clipboardHashtable.containsKey(idProxima) && !Clipboard.clipboardHashtable.containsKey(idPrevia)){
                //else if(Clipboard.clipboardVector.contains(maquina.proxima) && !Clipboard.clipboardVector.contains(maquina.previa)){                    
                    ComandoEM comandoEM = new ComandoEM(maquina,(Vector2)vector2);
                    comandoCUT.addComando(comandoEM);
                    ComandoIE comandoIE = new ComandoIE(maquina,(Vector2)vector2);
                    comandoCUTInverse.addComando(comandoIE);
                    maquina.deleteMachine(vector2);                        
                }
                
            }
                                    
        }
        
               
    }
    
    
    public static void copy(Vector vector2){
        if(state==Clipboard.STATE_CUT) return;
        state = Clipboard.STATE_COPY;
        Clipboard.clipboardVector.clear();
        fillClipboard(vector2);
        Clipboard.changeInicial = false;
        
    }
    
        
    public static void paste(Vector vector2,Hashtable dicOfMachines,int x0,int y0){
        
        if(Clipboard.clipboardMachine!=null){
            Clipboard.clipboardVector.clear();
            Clipboard.clipboardVector.add2(Clipboard.clipboardMachine);
            /*if(state==Clipboard.STATE_CUT){
                ComandoCUT comandoCUT = new ComandoCUT(null,null);
                ComandoCUT comandoCUTInverse = new ComandoCUT(null,null);
                comandoCUT.setInverse(comandoCUTInverse);
                comandoCUTInverse.addComando(new ComandoSPRInv2(clipboardMachine,null));
                comandoCUTInverse.addComando(new ComandoSPXInv2(clipboardMachine,null));
                clipboardMachine.previa = clipboardMachine.proxima = null;
                comandoCUT.addComando(new ComandoSPRInv2(clipboardMachine,null));
                comandoCUT.addComando(new ComandoSPXInv2(clipboardMachine,null));
                Comando.addComando2UR(comandoCUT);               
            }*/
        }
        
        switch(state){
            case Clipboard.STATE_COPY: 
                try{  

                 String xml="";
                 xml+="<jtv>\n";
                 xml+=Clipboard.clipboardVector.getXML();
                 xml+="</jtv>\n";
                 String headerXML ="<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>\n\n";
                 headerXML+="<!DOCTYPE jtv SYSTEM \""+JTV.pathJTV+"JTV.dtd\">\n\n";
                 xml = headerXML+xml;
                 //System.out.println(xml);
                 javax.xml.parsers.DocumentBuilderFactory builderFactory = javax.xml.parsers.DocumentBuilderFactory.newInstance();
                 javax.xml.parsers.DocumentBuilder builder = builderFactory.newDocumentBuilder();
                 org.w3c.dom.Document document = builder.parse (new org.xml.sax.InputSource (new StringReader(xml)));
                 ReferencesMachine.flagClipboard=true;
                 JTVScanner scanner = new JTVScanner (document);
                 scanner.visitDocument();
                 ReferencesMachine.flagClipboard=false;
                 //OBTENGO LA MAQUINA PRINCIPAL
                 //Hashtable dicOfMachines = scanner.getDicOfMachines();
                 Vector2 vector2Out = scanner.getPrincipal(); //(Vector2)dicOfMachines.get("CLIPBOARD");
                 if(!changeInicial){
                    vector2Out.inicial.setInicial(false);
                    vector2Out.inicial = null;
                 }
                                                     
                 Comando comando = new ComandoCOPY(null,null);
                 Comando comandoInverse = new ComandoCOPY(null,null);
                 comando.setInverse(comandoInverse);
                 Comando.addComando2UR(comando);

                 Enumeration en = vector2Out.elements();
                 int xMin=Integer.MAX_VALUE,yMin=Integer.MAX_VALUE;
                 while(en.hasMoreElements()){
                    Maquina maquina = (Maquina) en.nextElement();
                    if(maquina instanceof Enlace && maquina.proxima==null) continue;
                    if(maquina instanceof Submaquina){
                        ((Submaquina)maquina).machineComponents = (Vector2)dicOfMachines.get(((Submaquina)maquina).getNombreLargo());               
                    }
                    
                    comando.addComando(new ComandoCP(maquina,(Vector2)vector2));
                    comandoInverse.addComando(new ComandoCPI(maquina,(Vector2)vector2));                        
                    
                    if(!(maquina instanceof Enlace)){
                        xMin = Math.min(xMin,maquina.x0);
                        yMin = Math.min(yMin,maquina.y0);
                    }
                    vector2.add(maquina);
                 }
                 
                 en = null;
                 en = vector2Out.elements();
                 while(en.hasMoreElements()){
                    Maquina maquina = (Maquina) en.nextElement();
                    
                    if(!(maquina instanceof Enlace)){
                        maquina.x0+=(x0-xMin);
                        maquina.y0+=(y0-yMin);
                    }
                    else{
                        maquina.mover(x0-xMin,y0-yMin);
                       /*en = null; 
                       en = ((Enlace)maquina).getPuntos().elements();
                       while(en.hasMoreElements()){
                            Point point = (Point)en.nextElement();
                            point.setLocation((int)point.getX()+(x0-xMin),(int)point.getY()+(y0-yMin));
                       }*/
                   }
                    
                    maquina.updateBounds();
                 }
                 
            }
            catch(Exception ex){
                ex.printStackTrace();
            }
               break;
           case Clipboard.STATE_CUT:
               
               ComandoCUT comandoCUT = new ComandoCUT(null,null);
               ComandoCUT comandoCUTInverse = new ComandoCUT(null,null);
               comandoCUT.setInverse(comandoCUTInverse);
               Comando.addComando2UR(comandoCUT);
               int xMin=Integer.MAX_VALUE,yMin=Integer.MAX_VALUE;
               Enumeration en = Clipboard.clipboardVector.elements();
               while(en.hasMoreElements()){
                   Maquina maquina = (Maquina)en.nextElement();
                   
                   if(!(maquina instanceof Enlace)){
                       xMin = Math.min(xMin,maquina.x0);
                       yMin = Math.min(yMin,maquina.y0);
                   }
                                      
                   ComandoADD comandoADD = new ComandoADD(maquina,(Vector2)vector2);
                   comandoCUT.addComando(comandoADD);
                   ComandoRMV comandoRMV = new ComandoRMV(maquina,(Vector2)vector2);
                   comandoCUTInverse.addComando(comandoRMV);
                   vector2.add(maquina);
               }
               en = null;
               en = Clipboard.clipboardVector.elements();
               while(en.hasMoreElements()){
                   Maquina maquina = (Maquina)en.nextElement();
                   
                   if(!(maquina instanceof Enlace)){
                       
                       ComandoMM2 comandoMM2Inverse = new ComandoMM2(maquina,null);
                       maquina.x0+=(x0-xMin);
                       maquina.y0+=(y0-yMin);
                       ComandoMM2 comandoMM2 = new ComandoMM2(maquina,null);
                       comandoCUT.addComando(comandoMM2);
                       comandoCUTInverse.addComando(comandoMM2Inverse);
                       
                       if(clipboardMachine!=null){
                            comandoCUTInverse.addComando(new ComandoSPRInv2(clipboardMachine,null));
                            comandoCUTInverse.addComando(new ComandoSPXInv2(clipboardMachine,null));
                            clipboardMachine.previa = clipboardMachine.proxima = null;
                            comandoCUT.addComando(new ComandoSPRInv2(clipboardMachine,null));
                            comandoCUT.addComando(new ComandoSPXInv2(clipboardMachine,null));
                       }
                   }
                   else{
                       ComandoMM comandoMM = new ComandoMM(maquina,null,x0-xMin,y0-yMin);
                       comandoCUT.addComando(comandoMM);
                       ComandoMM comandoMMInverse = new ComandoMM(maquina,null,-x0+xMin,-y0+yMin);
                       comandoCUTInverse.addComando(comandoMMInverse);
                       maquina.mover(x0-xMin,y0-yMin);
                       /*en = null; 
                       en = ((Enlace)maquina).getPuntos().elements();
                       while(en.hasMoreElements()){
                            Point point = (Point)en.nextElement();
                            point.setLocation((int)point.getX()+(x0-xMin),(int)point.getY()+(y0-yMin));
                       }*/
                   }
                   maquina.updateBounds();
               }
               
               break;
        }   
        
        enabled = false;
        if(state==Clipboard.STATE_CUT || state==Clipboard.STATE_DELETE){
            state = Clipboard.STATE_NOTHING;            
        }
        Clipboard.clipboardMachine=null;
        sendMessage(false);
        
    }
        
    
    public static void delete(Vector vector2){
            
            enabled = false;
            sendMessage(false);
            Clipboard.cut(vector2);
            state = Clipboard.STATE_DELETE;
                                               
    }
    
     public static void startDaemonClipboard(JButton jButtonCut,JButton jButtonCopy,JButton jButtonDelete,JMenuItem jMenuItemCut, JMenuItem jMenuItemCopy, JMenuItem jMenuItemDelete){
        daemonClipboard = new DaemonClipboard(jButtonCut,jButtonCopy,jButtonDelete,jMenuItemCut, jMenuItemCopy, jMenuItemDelete);
        threadClipboard = new Thread(daemonClipboard);
        threadClipboard.setDaemon(true);
        threadClipboard.start();               
    }
    
    /** Getter for property enabled.
     * @return Value of property enabled.
     */
    public static boolean isEnabled() {
        return enabled;
    }    
    
    /** Setter for property enabled.
     * @param enabled New value of property enabled.
     */
    public static void setEnabled(boolean enabled) {
        Clipboard.enabled=enabled;
        //sendMessage();
    }
    
    /** Getter for property state.
     * @return Value of property state.
     */
    public static int getState() {
        return state;
    }
    
    /** Setter for property state.
     * @param state New value of property state.
     */
    public static void setState(int state) {
        Clipboard.state = state;        
    }
    
        public static class DaemonClipboard implements Runnable{
        
        public JButton jButtonCut, jButtonCopy, jButtonDelete;
        public JMenuItem jMenuItemCut, jMenuItemCopy, jMenuItemDelete;
        
        public DaemonClipboard(JButton jButtonCut,JButton jButtonCopy, JButton jButtonDelete,JMenuItem jMenuItemCut, JMenuItem jMenuItemCopy, JMenuItem jMenuItemDelete){
            this.jButtonCut = jButtonCut;
            this.jButtonCopy = jButtonCopy;            
            this.jButtonDelete = jButtonDelete;
            this.jMenuItemCut = jMenuItemCut;
            this.jMenuItemCopy = jMenuItemCopy;
            this.jMenuItemDelete = jMenuItemDelete;
        }
        
        public void sendMessage(boolean message){
            this.jButtonCut.setEnabled(message);
            this.jButtonCopy.setEnabled(message);
            this.jButtonDelete.setEnabled(message);
            this.jMenuItemCut.setEnabled(message);
            this.jMenuItemCopy.setEnabled(message);
            this.jMenuItemDelete.setEnabled(message);
        }
        
        public void run() {
            
            while(true){
                synchronized(monitor){
                    //if(enabled){
                        
                    this.jButtonCut.setEnabled(message);
                    this.jButtonCopy.setEnabled(message);
                    this.jButtonDelete.setEnabled(message);
                    this.jMenuItemCut.setEnabled(message);
                    this.jMenuItemCopy.setEnabled(message);
                    this.jMenuItemDelete.setEnabled(message);
                    //}
                    
                    try{
                        monitor.wait();
                    }
                    catch(Exception ex){
                        ex.printStackTrace();
                    }
                }
                              
            }
        }        
                        
    }

}
