package elaprendiz.estructuras;

import java.awt.Font;
import java.awt.Label;
import java.awt.Color;
import java.awt.Image;
import java.awt.Event;
import java.awt.Button;
import java.awt.Graphics;
import java.awt.TextField;
import java.awt.GridLayout;
import java.awt.FontMetrics;
import java.awt.BorderLayout;

import java.util.Vector;

//////////////////////////////////////////////////
// Classes needed to render objects upon the 
// screen

import elaprendiz.graficos.imagenes.ImageFrame;

import elaprendiz.awt.frame.FramedPanel;

//////////////////////////////////////////////////
// Class needed to perform operations upon data
// structure nodes

import elaprendiz.graficos.funciones.Funcion;

//////////////////////////////////////////////////
// Functions used for Binary Tree operations

import elaprendiz.estructuras.funciones.Insertar;
import elaprendiz.estructuras.funciones.Eliminar;
import elaprendiz.estructuras.funciones.Buscar;
import javax.swing.JPanel;


/**
 * Basic form of an Animated Data Structure Applet.
 */
public class ArbolBinario extends ImageFrame {

  final static String BASE_NODE = "Base Node";
  final static String HIGHLIGHT = "HighLight";

  final static int    NODE_SIZE = 25;

  int edgeSize = (int) Math.floor((double) NODE_SIZE / 10);

  ////////////////////////////////////////
  // Lienzo en la que se dibujara la animacion

  protected LienzoBinario animationCanvas;

  ////////////////////////////////////////
  // TextField que captura las entradas del usuario

  protected TextField field = new TextField();

  Label label = new Label("", Label.CENTER);
  Vector labelVector = new Vector();

  public synchronized final void createBaseNode() {
    Image image = createImage(NODE_SIZE + edgeSize, NODE_SIZE + edgeSize);

    Graphics graphics = image.getGraphics();
    graphics.setColor(TRANSPARENT_COLOR);
    graphics.fillOval(0, 0, NODE_SIZE + edgeSize, NODE_SIZE + edgeSize);

    graphics.setColor(Color.darkGray);
    graphics.fillOval(edgeSize, edgeSize, NODE_SIZE, NODE_SIZE);

    int[] xs = new int[3];
    int[] ys = new int[3];

    xs[0] = 0;
    xs[1] = 0;
    xs[2] = NODE_SIZE;

    ys[0] = 0;
    ys[1] = NODE_SIZE;
    ys[2] = 0;

    //borde color nodo
    //graphics.setColor(Color.blue.darker());
    //graphics.fillPolygon(xs, ys, 3);

    xs[0] = 0;
    xs[1] = NODE_SIZE;
    xs[2] = NODE_SIZE;

    ys[0] = NODE_SIZE;
    ys[1] = 0;
    ys[2] = NODE_SIZE;
    
    //borde color nodo
   // graphics.setColor(Color.blue.brighter());
    //graphics.fillPolygon(xs, ys, 3);
    

    //borde color nodo
    graphics.setColor(Color.blue.brighter());
    graphics.fillOval(edgeSize, edgeSize, NODE_SIZE - ((2 * edgeSize) ),
		      NODE_SIZE - ((2 * edgeSize) ));    
    
    graphics.dispose();

    image = filterImage(image);
    putImage(BASE_NODE, image);
  }

  
  public synchronized final void crearResaltado() {
    Image image = createImage((NODE_SIZE * 2) + 2 , (NODE_SIZE * 2) + 3);

    Graphics graphics = image.getGraphics();
    graphics.setColor(TRANSPARENT_COLOR);
    graphics.fillRect(0, 0, (NODE_SIZE * 2) + 2, (NODE_SIZE * 2) + 3);

    graphics.setColor(new Color(224, 224, 224));
    graphics.fillOval(1, 1, (NODE_SIZE * 2), (NODE_SIZE * 2));

    graphics.dispose();

    image = filterImage(image);
    putImage(HIGHLIGHT, image);
  }


  public synchronized final void crearNodoNuevo(String value) {
    Image image = copyImage(BASE_NODE);

    Graphics graphics = image.getGraphics();

    graphics.setFont(new Font("TimesRoman", Font.PLAIN, 14));
    FontMetrics fontMetrics = graphics.getFontMetrics();

    int xLocation = (int) Math.ceil((double) (NODE_SIZE -
      fontMetrics.stringWidth(value)) / 2);
    int yLocation = (int) Math.ceil((double) (NODE_SIZE -
      fontMetrics.getHeight()) / 2) + fontMetrics.getAscent();

    graphics.setColor(Color.black);
    graphics.drawString(value, (xLocation + 1), (yLocation + 1));
    graphics.setColor(Color.white);
    graphics.drawString(value, xLocation, yLocation);

    graphics.dispose();
    fontMetrics = null;

    image = filterImage(image);
    putImage(value, image);
  }
    

  public void init() {

    setLayout(new BorderLayout());

    animationCanvas = new LienzoBinario(this, (NODE_SIZE + edgeSize));

    JPanel buttonPanel = new JPanel();
    buttonPanel.setLayout(new GridLayout(0, 4));
    buttonPanel.add(new Button("Agregar"));
    buttonPanel.add(new Button("Eliminar"));
    buttonPanel.add(new Button("Buscar"));
    buttonPanel.add(field);

    FramedPanel frameOne   = new FramedPanel(4, null);
    FramedPanel frameTwo   = new FramedPanel(4, null);
    FramedPanel frameThree = new FramedPanel(4, null);

    frameOne.setLayout(new GridLayout(1,0));
    frameOne.add(buttonPanel);

    frameTwo.setLayout(new GridLayout(1,0));
    frameTwo.add(label);

    frameThree.setLayout(new GridLayout(1,0));
    frameThree.add(animationCanvas);

    add("North", frameOne);
    add("South", frameTwo);
    add("Center", frameThree);

    ////////////////////////////////////////
    // Create base node image and the high-
    // light image.

    createBaseNode();
    crearResaltado();

    validate();
  }

  public void updateLabel(String value) {
      label.setText(value);
  }

  public boolean action(Event evt, Object arg) {

    ////////////////////////////////////////
    // Retrieve user input (if any) from
    // text field.

    String value = field.getText();
    field.selectAll();

    int numericValue = 0;

    if ("Agregar".equals(arg)) {
      
      try {

	numericValue = Math.abs(Integer.parseInt(value) % 100);
	crearNodoNuevo("" + numericValue);
        //inserta nodo nuevo
	Funcion insert = new Insertar(numericValue, animationCanvas);
	insert.addObserver(animationCanvas);

	animationCanvas.addFunction(insert);

      } catch (NumberFormatException e) {

	numericValue = 0;
	field.setText("");

      }

      return true;
    }
    if ("Buscar".equals(arg)) {

      try {

	numericValue = Math.abs(Integer.parseInt(value) % 100);
	
	Funcion search = new Buscar(numericValue, animationCanvas);
	search.addObserver(animationCanvas);

	animationCanvas.addFunction(search);

      } catch (NumberFormatException e) {

	numericValue = 0;
	field.setText("");

      }

      return true;
    }
    if ("Eliminar".equals(arg)) {

      try {

	numericValue = Math.abs(Integer.parseInt(value) % 100);

	Funcion delete = new Eliminar(numericValue, animationCanvas);
	delete.addObserver(animationCanvas);

	animationCanvas.addFunction(delete);

      } catch (NumberFormatException e) {

	numericValue = 0;
	field.setText("");

      }

      return true;
    }

    return false;
  }
}
	
