package cl.jtv;
/*
 * Comando.java
 *
 * Created on 18 de febrero de 2003, 10:14 PM
 */

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

public abstract class Comando {

    protected Object artefacto;
    protected Vector2 vector2;
    protected Comando inverse;
    protected Vector comandos;
    
    public static int MAX_SIZE_UR=20;
    private static Vector vectorUndoRedo;
    private static int indexUR;
    private static boolean lastRedo;
    public static boolean flagDelete=false;
    
    private static DaemonUR daemonUR;
    private static Thread threadUR;
    private static JButton jButtonSave=null;
    private static JMenuItem jMenuItemSave=null;
    private static int indexURSave=0;
    /** Creates new Comando */
    public Comando(Object newArtefacto,Vector2 newVector2) {
        artefacto = newArtefacto;
        vector2 = newVector2;
        comandos = new Vector();
    }
    
    static{
        
        vectorUndoRedo = new Vector();
        indexUR = 0;
        lastRedo = true;
    }
    
    public static void setSaveComponents(JButton jButtonSave,JMenuItem jMenuItemSave){
        
        Comando.jButtonSave = jButtonSave;
        Comando.jMenuItemSave = jMenuItemSave;
    }
    
    public static void updateIndexURSave(){
        
        Comando.indexURSave = Comando.indexUR;
    }
    
    public static void addComando2UR(Comando comando){
        
        if((indexUR<vectorUndoRedo.size()-1)||(indexUR==vectorUndoRedo.size()-1 && !lastRedo)){            
            while(true){ 
                if(indexUR!=(vectorUndoRedo.size()-1))
                    vectorUndoRedo.removeElementAt(vectorUndoRedo.size()-1);
                else{
                    if(!lastRedo) vectorUndoRedo.removeElementAt(vectorUndoRedo.size()-1);                    
                    indexUR = vectorUndoRedo.size();                    
                    Comando.lastRedo=true;                                                            
                    break;
                }
            }
        }                                 
        Comando.vectorUndoRedo.add(comando);
        indexUR = vectorUndoRedo.size()-1;
        if(Comando.vectorUndoRedo.size()>Comando.MAX_SIZE_UR){
            Comando.vectorUndoRedo.removeElementAt(0);
            indexUR--;
        }
        synchronized(Comando.vectorUndoRedo){            
            Comando.vectorUndoRedo.notifyAll();
        }
    }
    
    
    
    public static boolean undo(){
        
        boolean out=true;
        
        if(!lastRedo) --indexUR;
        if(indexUR==0){
            indexUR=0;
            out=false;
        }
                
        ((Comando)Comando.vectorUndoRedo.get(indexUR)).getInverse().doIt();
        lastRedo = false;
        synchronized(Comando.vectorUndoRedo){
            Comando.vectorUndoRedo.notifyAll();
        }
        return out;
    }
    
    
    public static boolean redo(){
        
        boolean out=true;
        
        if(lastRedo) ++indexUR;
        if(indexUR==Comando.vectorUndoRedo.size()){
            indexUR=Comando.vectorUndoRedo.size()-1;
            out=false;
        }
                
        ((Comando)Comando.vectorUndoRedo.get(indexUR)).doIt();
        lastRedo = true;
        
        synchronized(Comando.vectorUndoRedo){
            Comando.vectorUndoRedo.notifyAll();
        }
        return out;
        
    }
    
    public static void reset(){
        
        Comando.vectorUndoRedo.clear();
        Comando.lastRedo=true;
        Comando.indexUR = 0;
         synchronized(Comando.vectorUndoRedo){
            daemonUR.setFlagUndoButton(true);
            Comando.vectorUndoRedo.notifyAll();
        }
        
    }
    
    public static int getIndexUR(){
        return Comando.indexUR;
    }
    
    public static void startDaemonUR(JButton jButtonUndo,JButton jButtonRedo,JMenuItem jMenuItemUndo,JMenuItem jMenuItemRedo){
        daemonUR = new DaemonUR(jButtonUndo,jButtonRedo,jButtonSave,jMenuItemUndo,jMenuItemRedo,jMenuItemSave);
        threadUR = new Thread(daemonUR);
        threadUR.setDaemon(true);
        threadUR.start();
        try{
            Thread.sleep(1000);
        }
        catch(Exception ex){
            ex.printStackTrace();
        }
        jButtonUndo.setEnabled(false);
        jMenuItemUndo.setEnabled(false);
    }
    
    /** Getter for property artefacto.
     * @return Value of property artefacto.
     */
    public java.lang.Object getArtefacto() {
        return artefacto;
    }    
    
    /** Setter for property artefacto.
     * @param artefacto New value of property artefacto.
     */
    public void setArtefacto(java.lang.Object artefacto) {
        this.artefacto = artefacto;
    }    

    /** Getter for property vector2.
     * @return Value of property vector2.
     */
    public Vector2 getVector2() {
        return vector2;
    }
    
    /** Setter for property vector2.
     * @param vector2 New value of property vector2.
     */
    public void setVector2(Vector2 vector2) {
        this.vector2 = vector2;
    }
    
    public void addComando(Comando comando){
        
        if(this.comandos==null) comandos = new Vector();
        this.comandos.add(comando);
    }
    
    public static Comando getLastComando(){
        
        return (Comando) Comando.vectorUndoRedo.lastElement();
    }
    
    public void doIt(){
                
        
        for(int i=0;i<comandos.size();i++)
            ((Comando)comandos.get(i)).doIt();
         
    }
    
    public Comando getInverse(){
        
        return inverse;
    }
    
    /** Setter for property inverse.
     * @param inverse New value of property inverse.
     */
    public void setInverse(Comando inverse) {
        this.inverse = inverse;
    }
    
    
    public static class DaemonUR implements Runnable{
        
        private JButton jButtonUndo, jButtonRedo, jButtonSave;
        private JMenuItem jMenuItemUndo,jMenuItemRedo, jMenuItemSave;
        private boolean flagUndoButton=false;
        
        public DaemonUR(JButton jButtonUndo,JButton jButtonRedo,JButton jButtonSave,JMenuItem jMenuItemUndo,JMenuItem jMenuItemRedo,JMenuItem jMenuItemSave){
            this.jButtonUndo = jButtonUndo;
            this.jButtonRedo = jButtonRedo;
            this.jButtonSave = jButtonSave;
            this.jMenuItemUndo = jMenuItemUndo;
            this.jMenuItemRedo = jMenuItemRedo;
            this.jMenuItemSave = jMenuItemSave;
        }
        
        public void run() {
            
            while(true){
                synchronized(Comando.vectorUndoRedo){
                    
                    this.jButtonUndo.setEnabled((Comando.indexUR==0 && Comando.lastRedo)|| indexUR>0);
                    this.jButtonRedo.setEnabled((Comando.indexUR==Comando.vectorUndoRedo.size()-1 && !Comando.lastRedo)|| indexUR<Comando.vectorUndoRedo.size()-1);
                    this.jMenuItemUndo.setEnabled(jButtonUndo.isEnabled());
                    this.jMenuItemRedo.setEnabled(jButtonRedo.isEnabled());
                    
                    if(flagUndoButton){
                        this.jButtonUndo.setEnabled(false);
                        this.jMenuItemUndo.setEnabled(false);
                        flagUndoButton = false;                        
                    }
                    
                    try{
                        Comando.vectorUndoRedo.wait();
                    }
                    catch(Exception ex){
                        ex.printStackTrace();
                    }
                    if(!flagUndoButton){
                        this.jButtonSave.setEnabled(true);
                        this.jMenuItemSave.setEnabled(true);
                    }
                }               
            }
        }        
                        
        /** Getter for property jButtonUndo.
         * @return Value of property jButtonUndo.
         */
        public javax.swing.JButton getJButtonUndo() {
            return jButtonUndo;
        }
                        
        /** Getter for property flagUndoButton.
         * @return Value of property flagUndoButton.
         */
        public boolean isFlagUndoButton() {
            return flagUndoButton;
        }
        
        /** Setter for property flagUndoButton.
         * @param flagUndoButton New value of property flagUndoButton.
         */
        public void setFlagUndoButton(boolean flagUndoButton) {
            this.flagUndoButton = flagUndoButton;
        }
        
    }    
}
