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

import Colecciones_SEED.Cola;
import Colecciones_SEED.ListaCD;
import Colecciones_SEED.NodoEneario;
import Colecciones_SEED.Pila;
import javafx.animation.KeyFrame;
import javafx.animation.KeyValue;
import javafx.animation.Timeline;
import javafx.scene.control.Label;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.util.Duration;
/**
 *
 * @author usuario
 */
public class ArbolEnearioG {
    
    private NodoEnearioG raiz;
    private Pila<Circle> pila;
    private Pila<Label> lab;
    private Pila<Line> lin;

    /**
     *
     */
    public ArbolEnearioG() {
        this.raiz = null;
        pila = new Pila();
        lab = new Pila();
        lin = new Pila();
    }

    /**
     *
     * @return
     */
    public NodoEnearioG getRaiz() {
        return raiz;
    }

    /**
     *
     * @return
     */
    public Pila<Circle> getPila() {
        return pila;
    }

    /**
     *
     * @param pila
     */
    public void setPila(Pila<Circle> pila) {
        this.pila = pila;
    }

    /**
     *
     * @return
     */
    public Pila<Label> getLab() {
        return lab;
    }

    /**
     *
     * @param lab
     */
    public void setLab(Pila<Label> lab) {
        this.lab = lab;
    }

    /**
     *
     * @return
     */
    public Pila<Line> getLin() {
        return lin;
    }

    /**
     *
     * @param lin
     */
    public void setLin(Pila<Line> lin) {
        this.lin = lin;
    }

    /**
     *
     * @param raiz
     */
    public void setRaiz(NodoEnearioG raiz){
        this.raiz = raiz;
    }

    /**
     *
     * @param raiz
     */
    public void crearArbol(NodoEneario r) {
        if(r==null){
            this.setRaiz(null);
            return;
        }
        this.setRaiz(new NodoEnearioG((int) r.getInfo(),this.pila.desapilar(),this.lab.desapilar(),null,null));
        this.raiz.setHijo(crear(r.getHijo()));
    }
    
    private NodoEnearioG crear(NodoEneario r) {
        if(r==null)
            return (null);
        NodoEnearioG hijo = new NodoEnearioG((int) r.getInfo(),this.pila.desapilar(),this.lab.desapilar(),null,null);
        hijo.setHijo(crear(r.getHijo()));
        hijo.setHermano(crear(r.getHermano()));
        return (hijo);
    }

    /**
     *
     * @param nodos
     */
    public void cargarNodos(Circle[] nodos) {
        for(int i=0; i<nodos.length; i++)
            this.pila.apilar(nodos[i]);
    }

    /**
     *
     * @param labels
     */
    public void cargarLabels(Label[] labels) {
        for(int i=0; i<labels.length; i++)
            this.lab.apilar(labels[i]);
    }

    /**
     *
     * @param lineas
     */
    public void cargarLineas(Line[] lineas) {
        for(int i=0; i<lineas.length; i++)
            this.lin.apilar(lineas[i]);
    }

    /**
     *
     * @param alt
     */
    public void pintarArbol(){
        
        Circle c ;
        Label l ;
        double lx1=200.0, ly1=210.0, lx2=189.0, ly2=204.0;
        
        Label label = this.lab.desapilar();
        label.setPrefHeight(10.0);
        label.setPrefWidth(50.0);
        label.setLayoutX(lx2-50.0);
        label.setLayoutY(ly2);
        label.setText("<Raiz>");
        label.setTextFill(Color.GRAY);
        label.setVisible(true);
        
        if(this.raiz==null){
            c = this.pila.desapilar();
            l = this.lab.desapilar();   
            c.setLayoutX(lx1);
            c.setLayoutY(ly1);
            l.setLayoutX(lx2);
            l.setLayoutY(ly2);
            c.setFill(Color.GRAY);
            c.setStroke(Color.BLACK);
            l.setText("Null");            
            c.setVisible(true);
            l.setVisible(true);
            
            return;
        }        
        c = this.raiz.getC();
        l = this.raiz.getL();
        c.setLayoutX(lx1);
        c.setLayoutY(ly1);
        l.setLayoutX(lx2);
        l.setLayoutY(ly2);
        c.setFill(Color.GREENYELLOW);
        c.setStroke(Color.GREEN);
        l.setText(raiz.getInfo()+"");            
        c.setVisible(true);
        l.setVisible(true);
        
        //Pintar Hijos y hermanos
        pintar(raiz.getHijo(),lx1,ly1+40.0,lx2,ly2+40.0);
        if(raiz.getHijo()!=null){
            Line l2;
            l2 = this.lin.desapilar();                        
            l2.setLayoutX(raiz.getC().getLayoutX());
            l2.setLayoutY(raiz.getC().getLayoutY());
            l2.setStartX(0.0);
            l2.setEndX(0.0);
            l2.setStartY(0.0);
            l2.setEndY(40.0);
            l2.setVisible(true);
        }
//        this.reajustarColores();
    }
    
    
    private void pintar(NodoEnearioG r, double lx1, double ly1, double lx2, double ly2) {
        if(r==null)
            return;
        
        boolean v = true;
        if(lx1>=850.0){
            v = false;
            System.err.println("El Arbol no puede pintarse en su Totalidad!");
        }
        Circle c ;
        Label l ;
        c = r.getC();
        l = r.getL();
        c.setLayoutX(lx1);
        c.setLayoutY(ly1);
        l.setLayoutX(lx2);
        l.setLayoutY(ly2);
        c.setFill(Color.GREENYELLOW);
        c.setStroke(Color.GREEN);
        l.setText(r.getInfo()+"");            
        if(v){
            c.setVisible(true);
            l.setVisible(true);
        }
        //Si tiene Hijo
        if(r.getHijo()!=null){
            pintar(r.getHijo(),lx1,ly1+40.0,lx2,ly2+40.0);
            Line l2;
            l2 = this.lin.desapilar();                        
            l2.setLayoutX(r.getC().getLayoutX());
            l2.setLayoutY(r.getC().getLayoutY());
            l2.setStartX(0.0);
            l2.setEndX(0.0);
            l2.setStartY(0.0);
            l2.setEndY(40.0);
            if(v)
            l2.setVisible(true);            
        }
        
        if(r.getHermano()!=null){
            int h = r.getHijo()!=null?(this.numHijos(r.getInfo())):0;
            int ajuste = (40);
            if(h!=0)
                ajuste = (40*(h+1));       
            pintar(r.getHermano(),(lx1+ajuste),ly1,(lx2+ajuste),ly2);            
            Line l2;
            l2 = this.lin.desapilar();                        
            l2.setLayoutX(r.getC().getLayoutX());
            l2.setLayoutY(r.getC().getLayoutY());
            l2.setStartX(0.0);
            l2.setEndX(ajuste);
            l2.setStartY(0.0);
            l2.setEndY(0.0);
            if(v)
            l2.setVisible(true);
        }
        
    }
    
    private NodoEnearioG buscar(NodoEnearioG r, int dato){
       NodoEnearioG q, s;
       if(r==null)
           return (r);
       if(r.getInfo()==dato){
           return (r);
       }
       q = r.getHijo();
       while(q != null){
           s = buscar(q, dato);
           if(s != null){
               return (s);
           }
           q = q.getHermano();
       }
       return (null);
    }
    
    public int numHijos(int padre){
        NodoEnearioG p = this.buscar(this.raiz, padre);
        int cant = numHijos(p);
        return (cant);
    }
     
    private int numHijos(NodoEnearioG r){       
       NodoEnearioG q;
       int cant = 0;
        if(r!=null){
            q = r.getHijo();
            if(q != null){
                cant += numHijos(q);
                q = q.getHermano();
                while(q != null){
                    cant++;
                    cant += numHijos(q);
                    q = q.getHermano();
                }
            }
        }
        return (cant);
   }
    
    
    /**
     *
     * @param i 
     * @param dato
     * @param tl  
     */
    public void animacion(int i, int dato, Timeline tl) {
        tl = new Timeline();
        tl.setCycleCount(1);
        tl.getKeyFrames().removeAll();
        switch(i){
            //Insertar 0
            case 0:
                this.pintarInsertado(dato, tl);
                break;
            //Eliminar 1
            case 1:
                //this.pintarEliminado(dato, tl);
                break;
            //Buscar 2
            case 2:
                this.buscarG(dato, tl);
                break;
            //Hojas 3
            case 3:
                this.getHojas();
                break;
            //Podar 4
            case 4:
                this.getHojas();
                break;
            // preorden 5
            case 5:
                this.preOrden(tl);
                break;
            // inorden 6
            case 6:
                this.inOrden(tl);
                break;
            //postorden 7
            case 7:
                this.postOrden(tl);
                break;
            //niveles 8
            case 8:
                this.impNiveles(tl);
                break;
        }
    }
    
    /**
     *
     * @param dato
     * @param tl
     */
    public void pintarInsertado(int dato, Timeline tl){
        double durac = 0;
        NodoEnearioG n = this.buscar(this.raiz, dato);
        if(n!=null){
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().setAll(
                new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)),
                new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));
                tl.play();
            }
        }
    }
    
    /**
     *
     * @param x
     * @param tl
     * @return
     */
    public boolean buscarG(int x, Timeline tl){
        ListaCD<NodoEnearioG> l=new ListaCD<NodoEnearioG>();
        boolean rta = this.buscarG(raiz, x, l);
        int durac = 0;
        for(int i=0; i<l.getTamanio(); i++){
            NodoEnearioG n = l.get(i);
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)));
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));                
            }
            durac+=1000;
        }
        tl.play();
        return (rta);
    }
    
    private boolean buscarG(NodoEnearioG r, int x, ListaCD<NodoEnearioG> l){
       NodoEnearioG q;
       boolean s;
       if(r==null)
           return (false);
       l.insertarAlFinal(r);
       if(r.getInfo()==x){
           return (true);
       }
       q = r.getHijo();
       while(q != null){
           s = buscarG(q, x, l);
           if(s){
               return (true);
           }
           q = q.getHermano();
       }
       return (false);
    }
    
    /**
     *
     */
    public void getHojas(){
        getHojas(raiz);
    }
    
    private void getHojas(NodoEnearioG r){
        NodoEnearioG q;
        if(r==null)
            return ;
        q = r.getHijo();
        if(q==null){
            if(r.getC().getLayoutX()<850.0){
                r.getC().setFill(Color.BEIGE);
                r.getC().setStroke(Color.RED);
            }
            return ;            
        }
        while(q != null){
        getHojas(q);
        q = q.getHermano();
        }
    }
    
    /**
     *
     * @param tl
     */
    public void preOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoEnearioG> l=new ListaCD<NodoEnearioG>();
         preOrden(this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoEnearioG n = l.get(i);
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)));
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));
            }
            durac+=1000;
        }
        tl.play();
    }

    private void  preOrden(NodoEnearioG r, ListaCD<NodoEnearioG> l){
        NodoEnearioG q;
        if(r!=null){
            l.insertarAlFinal(r);
            q = r.getHijo();
            if(q != null){
                preOrden(q,l);
                q = q.getHermano();
                while(q != null){
                    preOrden(q,l);
                    q = q.getHermano();
                }
            }
        }
    }
    
    /**
     *
     * @param tl
     */
    public void inOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoEnearioG> l=new ListaCD<NodoEnearioG>();
         inOrden(this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoEnearioG n = l.get(i);
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)));
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));
            }
            durac+=1000;
        }
        tl.play();
    }

    private void  inOrden(NodoEnearioG r, ListaCD<NodoEnearioG> l){
        NodoEnearioG q;
        if(r!=null){
            q = r.getHijo();
            if(q == null){
                l.insertarAlFinal(r);
            }else{
                inOrden(q,l);
                l.insertarAlFinal(r);
                q = q.getHermano();
                while(q != null){
                    inOrden(q,l);
                    q = q.getHermano();
                }
            }
        }
    }

   
    /**
     *
     * @param tl
     */
    public void postOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoEnearioG> l=new ListaCD<NodoEnearioG>();
         postOrden(this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoEnearioG n = l.get(i);
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)));
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));
            }
            durac+=1000;
        }
        tl.play();
    }
    
    private void postOrden(NodoEnearioG r, ListaCD<NodoEnearioG> l){
        NodoEnearioG q;
        if(r!=null){
            q = r.getHijo();
            while(q != null){
                postOrden(q,l);
                q = q.getHermano();
            }
            l.insertarAlFinal(r);
        }
    }
    
    /**
     *
     * @param tl
     */
    public void impNiveles(Timeline tl){
        int durac =0;
        ListaCD<NodoEnearioG> l=new ListaCD<NodoEnearioG>();
        this.impNiveles(l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoEnearioG n = l.get(i);
            if(n.getC().getLayoutX()<850.0){
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),Color.GREEN)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.RED)));
                tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),Color.GREENYELLOW)),
                new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BEIGE)));
            }
            durac+=1000;
        }
        tl.play();
    }
    
    
    private void impNiveles(ListaCD<NodoEnearioG> l){        
        Cola<NodoEnearioG> c = new Cola();
        if(this.esVacio())
            return;
        NodoEnearioG s, q;
        c.enColar(this.raiz);
        while(!c.esVacia()){
            q = c.deColar();
            if(q!=null){
                l.insertarAlFinal(q);
                s = q.getHijo();
                while(s!=null){
                    c.enColar(s);
                    s = s.getHermano();
                }
            }            
        }
    }

    /**
     *
     * @return
     */
    public boolean esVacio(){
        return(this.raiz==null);
    }

    /**
     *
     * @param dato
     * @return
     */
    public String getLayoutsEliminar(int dato) {
        NodoEnearioG n = this.buscar(raiz, dato);
        double lx1=0, lx2=0, lx3=0, lx4=0;
        if(n!=null){            
            lx1 = n.getC().getLayoutX();
            lx2 = n.getC().getLayoutY();
            lx3 = n.getL().getLayoutX();
            lx4 = n.getL().getLayoutY();
        }        
        return (lx1+"_"+lx2+"_"+lx3+"_"+lx4);
    }

    /**
     *
     * @param layouts
     * @param dato
     * @param tl
     * @param c
     * @param l
     */
    public void animacionEliminar(String layouts, int dato, Timeline tl, Circle c, Label l) {
        tl = new Timeline();
        tl.setCycleCount(1);
        tl.getKeyFrames().removeAll();
        String v[] = layouts.split("_");
        c.setLayoutX(Double.parseDouble(v[0]));
        c.setLayoutY(Double.parseDouble(v[1]));
        l.setLayoutX(Double.parseDouble(v[2]));
        l.setLayoutY(Double.parseDouble(v[3]));
        l.setText(dato+"");
        
        if(c.getLayoutX()<850.0){
            c.setVisible(true);
            l.setVisible(true);
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(c.strokeProperty(),Color.GREEN)),
            new KeyFrame(new Duration(2000), new KeyValue(c.strokeProperty(),Color.RED)));
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(c.fillProperty(),Color.GREENYELLOW)),
            new KeyFrame(new Duration(2000), new KeyValue(c.fillProperty(),Color.BEIGE)));            
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(c.translateYProperty(),0)),
            new KeyFrame(new Duration(3000), new KeyValue(c.translateYProperty(),440-c.getLayoutY())));            
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(l.translateYProperty(),0)),
            new KeyFrame(new Duration(3000), new KeyValue(l.translateYProperty(),434-l.getLayoutY())));            
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(2000), new KeyValue(c.visibleProperty(),true)),
            new KeyFrame(new Duration(3000), new KeyValue(c.visibleProperty(),false)));            
            tl.getKeyFrames().addAll(new KeyFrame(new Duration(2000), new KeyValue(l.visibleProperty(),true)),
            new KeyFrame(new Duration(3000), new KeyValue(l.visibleProperty(),false)));   
            tl.play();
        }
        
    }
    

    
}
