/*
 * 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.NodoRN;
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.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.util.Duration;

/**
 *
 * @author usuario
 */
public class ArbolRojiNegroG  extends ArbolBBG{

    public ArbolRojiNegroG() {
        super();
    }
    
    
    public void crearArbol(NodoRN raiz) {
        super.setRaiz(crearRN(raiz));        
    }
    
    private NodoRNG crearRN(NodoRN r) {
        if(r==null || r.getInfo()==null)
            return (null);
        else
        {
            NodoRNG aux=new NodoRNG(r.getColor(), (int) r.getInfo(), super.getPila().desapilar(), super.getLab().desapilar(), crearRN(r.getIzq()), crearRN(r.getDer()));
            return (aux);
        }
    }    
    
    /**
     *
     * @param alt
     */
    @Override
    public void pintarArbol(int alt){
        if(super.getRaiz()==null){
            Circle c = super.getPila().desapilar();
            Label l = super.getLab().desapilar();   
            c.setLayoutX(512.0);
            c.setLayoutY(195.0);
            l.setLayoutX(501.0);
            l.setLayoutY(189.0);
            c.setFill(Color.GRAY);
            c.setStroke(Color.BLACK);
            l.setText("Null");   
            l.setTextFill(Color.BLACK);
            c.setVisible(true);
            l.setVisible(true);
            return;
        }
        int ajuste = 0;
        switch(alt){
            case 0: ajuste = 0; break;
            case 1: ajuste = 1; break;
            case 2: ajuste = 2; break;
            case 3: ajuste = 4; break;
            case 4: ajuste = 8; break;
            case 5: ajuste = 16;break;
            case 6: ajuste = 32;break;
            case 7: ajuste = 64;break;
        }
        this.pinta((NodoRNG) super.getRaiz(),null,ajuste);
    }
    
    private Paint getColor(int c){
        if(c==0)
            return (Color.RED);
        return (Color.BLACK);
    }

    private void pinta(NodoRNG r, NodoRNG padre, int ajuste) {        
        Line l;        
        ajuste = ajuste/2;
        if(r==null){
            return;
        }        
        r.getC().setVisible(true);
        r.getC().setFill(getColor(r.getColor()));
        r.getC().setStroke(getColor(r.getColor()));
        r.cargarLabel();
        r.getL().setVisible(true);
        if(padre==null){
            r.getC().setLayoutX(512.0);
            r.getC().setLayoutY(195.0);
            r.getC().setFill(getColor(r.getColor()));
            r.getC().setStroke(getColor(r.getColor()));
            r.cargarLabel();
            r.getL().setLayoutX(501.0);
            r.getL().setLayoutY(189.0);
            r.getC().setVisible(true);
            r.getL().setVisible(true);
        }
        if(r.getIzq()!=null){
            r.getIzq().getC().setLayoutX(r.getC().getLayoutX()-(15*ajuste));
            r.getIzq().getC().setLayoutY(r.getC().getLayoutY()+50.0);
            r.getIzq().getC().setFill(getColor(r.getIzq().getColor()));
            r.getIzq().getC().setStroke(getColor(r.getIzq().getColor()));
            r.getIzq().cargarLabel();
            r.getIzq().getL().setLayoutX(r.getL().getLayoutX()-(15*ajuste));
            r.getIzq().getL().setLayoutY(r.getL().getLayoutY()+50.0);
            r.getIzq().getC().setVisible(true);
            r.getIzq().getL().setVisible(true);            
            l = super.getLin().desapilar();            
            l.setLayoutX(r.getC().getLayoutX());
            l.setLayoutY(r.getC().getLayoutY());
            l.setStartX(0.0);
            l.setEndX(-(15*ajuste));
            l.setStartY(0.0);
            l.setEndY(50.0);
            l.setVisible(true);
            
        }
        if(r.getDer()!=null){
            r.getDer().getC().setLayoutX(r.getC().getLayoutX()+(15*ajuste));
            r.getDer().getC().setLayoutY(r.getC().getLayoutY()+50.0);
            r.getDer().getC().setFill(getColor(r.getDer().getColor()));
            r.getDer().getC().setStroke(getColor(r.getDer().getColor()));
            r.getDer().cargarLabel();
            r.getDer().getL().setLayoutX(r.getL().getLayoutX()+(15*ajuste));
            r.getDer().getL().setLayoutY(r.getL().getLayoutY()+50.0);
            r.getDer().getC().setVisible(true);
            r.getDer().getL().setVisible(true);
            l = super.getLin().desapilar();                        
            l.setLayoutX(r.getC().getLayoutX());
            l.setLayoutY(r.getC().getLayoutY());
            l.setStartX(0.0);
            l.setEndX((15*ajuste));
            l.setStartY(0.0);
            l.setEndY(50.0);
            l.setVisible(true);            
        }
        pinta(r.getIzq(),r,ajuste);
        pinta(r.getDer(),r,ajuste);
    }
    
     /**
     *
     * @param i 
     * @param dato
     * @param tl  
     */
    @Override
    public void animacion(int i, int dato, Timeline tl) {
        this.reajustarColores();
        tl = new Timeline();
        tl.setCycleCount(1);
        tl.getKeyFrames().removeAll();
        switch(i){
            //Insertar 0
            case 0:
                this.pintarInsertado(dato, tl);
                break;
            //Eliminar 1
            case 1:
                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
     */
    @Override
    public void pintarInsertado(int dato, Timeline tl){
        double durac = 0;
        NodoRNG n = this.buscar((NodoRNG)super.getRaiz(), dato);
        if(n!=null){
            tl.getKeyFrames().setAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
//            new KeyFrame(new Duration(durac), new KeyValue(n.getC().fillProperty(),n.getC().getFill())),
//            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().fillProperty(),Color.BLUE)));
            tl.play();
        }
    }
    
    private NodoRNG buscar(NodoRNG r, int x){
        if (r==null)
            return (null);
        if(r.getInfo()==x)
            return (r);
        else
        {
            NodoRNG aux=(r.getIzq()==null)?null:buscar(r.getIzq(),x);
            if(aux!=null)
                return (aux);
            else
                return (r.getDer()==null)?null:buscar(r.getDer(),x);
        }
    }
    
    /**
     *
     * @param x
     * @param tl
     * @return
     */
    @Override
    public boolean buscarG(int x, Timeline tl){
        ListaCD<NodoRNG> l=new ListaCD<NodoRNG>();
        boolean rta = this.buscarG((NodoRNG)super.getRaiz(), x, l);
        int durac = 0;
        for(int i=0; i<l.getTamanio(); i++){
            NodoRNG n = l.get(i);
            tl.getKeyFrames().addAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
            durac+=1000;
        }
        tl.play();
        return (rta);
    }
    
    private boolean buscarG(NodoRNG r, int x, ListaCD<NodoRNG> l){
        if (r==null)
            return (false);
        l.insertarAlFinal(r);
        int compara=((Comparable)r.getInfo()).compareTo(x);
        if(compara>0)
            return(buscarG(r.getIzq(),x,l));
        else
            if(compara<0)
                return(buscarG(r.getDer(),x,l));                            
            else
                return (true);
    }
    
    /**
     *
     */
    @Override
    public void getHojas(){
        getHojas((NodoRNG) super.getRaiz());
    }
    
    private void getHojas(NodoRNG r){
        if (r!=null){
            if(this.esHoja(r)){
                r.getC().setStroke(Color.YELLOW);
            }
            getHojas(r.getIzq());
            getHojas(r.getDer());
        }
    }
    
    private boolean esHoja(NodoRNG x){
        return (x!=null && x.getIzq()==null && x.getDer()==null);
    }
    
    /**
     *
     * @param tl
     */
    @Override
    public void preOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoRNG> l=new ListaCD<NodoRNG>();
         preOrden((NodoRNG)this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoRNG n = l.get(i);
            tl.getKeyFrames().addAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
            durac+=1000;
        }
        tl.play();
    }

    private void  preOrden(NodoRNG r, ListaCD<NodoRNG> l){
        if(r!=null){
            l.insertarAlFinal(r);
            preOrden(r.getIzq(), l);
            preOrden(r.getDer(), l);
        }
    }
    
    /**
     *
     * @param tl
     */
    @Override
    public void inOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoRNG> l=new ListaCD<NodoRNG>();
         inOrden((NodoRNG)this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoRNG n = l.get(i);
            tl.getKeyFrames().addAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
            durac+=1000;
        }
        tl.play();
    }

    private void  inOrden(NodoRNG r, ListaCD<NodoRNG> l){
        if(r!=null){
            inOrden(r.getIzq(), l);
            l.insertarAlFinal(r);
            inOrden(r.getDer(), l);
        }
    }

   
    /**
     *
     * @param tl
     */
    @Override
    public void postOrden(Timeline tl){
        int durac =0;
        ListaCD<NodoRNG> l=new ListaCD<NodoRNG>();
         postOrden((NodoRNG)this.getRaiz(),l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoRNG n = l.get(i);
            tl.getKeyFrames().addAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
            durac+=1000;
        }
        tl.play();
    }
    
    private void postOrden(NodoRNG r, ListaCD<NodoRNG> l){
        if(r!=null){
            postOrden(r.getIzq(), l);
            postOrden(r.getDer(), l);
            l.insertarAlFinal(r);
        }
    }
    
    /**
     *
     * @param tl
     */
    @Override
    public void impNiveles(Timeline tl){
        int durac =0;
        ListaCD<NodoRNG> l=new ListaCD<NodoRNG>();
        this.impNiveles(l);
        for(int i=0; i<l.getTamanio(); i++){
            NodoRNG n = l.get(i);
            tl.getKeyFrames().addAll(
            new KeyFrame(new Duration(durac), new KeyValue(n.getC().strokeProperty(),n.getC().getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(n.getC().strokeProperty(),Color.YELLOW)));
            durac+=1000;
        }
        tl.play();
    }
    
    
    private void impNiveles(ListaCD<NodoRNG> l){        
        if(!this.esVacio()){
            Cola<NodoRNG> c=new Cola<>();
            c.enColar((NodoRNG)this.getRaiz());
            NodoRNG x;
                while(!c.esVacia()){
                    x=c.deColar();
                    l.insertarAlFinal(x);
                    if(x.getIzq()!=null)
                    c.enColar(x.getIzq());
                    if(x.getDer()!=null)
                    c.enColar(x.getDer());
                }
        }
    }

    /**
     *
     * @return
     */
    @Override
    public boolean esVacio(){
        return(super.getRaiz()==null);
    }

    /**
     *
     * @param dato
     * @return
     */
    @Override
    public String getLayoutsEliminar(int dato) {
        NodoRNG n = this.buscar((NodoRNG)super.getRaiz(), 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
     */
    @Override
    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+"");
        c.setVisible(true);
        l.setVisible(true);
        double durac = 0.0;
        tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(c.strokeProperty(),c.getStroke())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(c.strokeProperty(),Color.YELLOW)));  
        tl.getKeyFrames().addAll(new KeyFrame(new Duration(durac), new KeyValue(c.fillProperty(),c.getFill())),
            new KeyFrame(new Duration((durac+1000)), new KeyValue(c.fillProperty(),Color.ORANGE)));  
        tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(c.translateYProperty(),0)),
        new KeyFrame(new Duration(3000), new KeyValue(c.translateYProperty(),400-c.getLayoutY())));            
        tl.getKeyFrames().addAll(new KeyFrame(new Duration(0), new KeyValue(l.translateYProperty(),0)),
        new KeyFrame(new Duration(3000), new KeyValue(l.translateYProperty(),394-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();
    }
    
    @Override
    public void reajustarColores(){
        this.reajustarColores((NodoRNG) super.getRaiz());
    }
    
    private void reajustarColores(NodoRNG r){
        if(r==null){
            return;
        }
        r.getC().setFill(this.getColor(r.getColor()));
        r.getC().setStroke(this.getColor(r.getColor()));
        reajustarColores(r.getIzq());
        reajustarColores(r.getDer());
    }
    
    
    
    
    
}
