package elaprendiz.estructuras.funciones;

import elaprendiz.graficos.funciones.Funcion;

import java.awt.Point;

import java.util.Observer;
import java.util.Observable;

import elaprendiz.graficos.imagenes.ImageFrame;
import elaprendiz.graficos.imagenes.ObjetoImagen;

import elaprendiz.estructuras.nodos.Nodo;
import elaprendiz.estructuras.nodos.ArbolNodo;
import elaprendiz.estructuras.EstructuraLienzo;
import elaprendiz.estructuras.LienzoBinario;

public class Buscar extends Funcion implements Observer {

  ////////////////////////////////////////
  // Reference to LienzoBinario so that 
  // Highlight function maybe added to list
  // of functions

  LienzoBinario canvas;

  ////////////////////////////////////////
  // The node to be found.

  ArbolNodo buscarNodo;

  ////////////////////////////////////////
  // Reference used to trapse down the bi-
  // nary tree

  ArbolNodo trapseNode;

  ////////////////////////////////////////
  // Whether or not the current function 
  // is blocking (not executing) until 
  // another function completes its task.

  boolean bloqueado = false;

  String actualizarInfo = "";

  public Buscar(int value, LienzoBinario canvas) {
    this.canvas = canvas;
    buscarNodo = new ArbolNodo(new Point(0, 0), canvas.frame, value);
  }


  public void update(Observable observed, Object arg) {
    if (observed instanceof Resaltar) {
      bloqueado = false;
    }
  }

  public void performFuncion() {

    if (bloqueado) {

      setChanged();
      notifyObservers(actualizarInfo);

    }
    else {

      ////////////////////////////////////////
      // The tree is empty or the requested 
      // node was not found so report that 
      // search failed.

      if (canvas.getRootNode() == null) {

	////////////////////////////////////////
	// Notify observers that search failed.

	setChanged();
	notifyObservers((Object) "Search Failed");

	setChanged();
	notifyObservers((Object) null);

	////////////////////////////////////////
	// Nothing else to do, so indicate done.

	terminado = true;
      }

      else if (trapseNode == null) {

	trapseNode = canvas.getRootNode();

	actualizarInfo = "Beginning Search at Root Node : " + trapseNode.
	  getValue();
	
	setChanged();
	notifyObservers((Object) actualizarInfo);

	Funcion highLight = new Resaltar(trapseNode, canvas);
	highLight.addObserver(this);

	canvas.addFunction(highLight);

	bloqueado = true;
      }

      ////////////////////////////////////////
      // Else, do comparison on trapse node
      // and either report success or continue
      // Buscar process on the next node (either
      // left or right child of current node).

      else {
	  
	if (trapseNode.menorQue(buscarNodo)) {
	  
	  trapseNode = trapseNode.getLeftChild();
	
	  if (trapseNode == null) {
	    
	    ////////////////////////////////////////
	    // Notify observers that search failed.

	    setChanged();
	    notifyObservers((Object) "Search Failed");

	    setChanged();
	    notifyObservers((Object) null);

	    ////////////////////////////////////////
	    // Nothing else to do, so indicate done.

	    terminado = true;
	  }
	  else {

	    Funcion highLight = new Resaltar(trapseNode, canvas);
	    highLight.addObserver(this);
	    
	    canvas.addFunction(highLight);

	    actualizarInfo = "Node : " + trapseNode.getValue() + " Compared with" +
	      " Value : " + buscarNodo.getValue();
	  
	    setChanged();
	    notifyObservers((Object) actualizarInfo);

	    ////////////////////////////////////////
	    // Wait until the Resaltar function
	    // terminates (Insert will receive noti-
	    // fication of this via functionFinished)

	    bloqueado = true;
	  }
	}
	else if (trapseNode.mayorQue(buscarNodo)) {
	  
	  trapseNode = trapseNode.getRightChild();

	  if (trapseNode == null) {
	    
	    ////////////////////////////////////////
	    // Notify observers that search failed.

	    setChanged();
	    notifyObservers((Object) "Search Failed");

	    setChanged();
	    notifyObservers((Object) null);

	    ////////////////////////////////////////
	    // Nothing else to do, so indicate done.

	    terminado = true;
	  }
	  else {

	    Funcion highLight = new Resaltar(trapseNode, canvas);
	    highLight.addObserver(this);
	    
	    canvas.addFunction(highLight);

	    actualizarInfo = "Node : " + trapseNode.getValue() + " Compared with" +
	      " Value : " + buscarNodo.getValue();
	  
	    setChanged();
	    notifyObservers((Object) actualizarInfo);

	    ////////////////////////////////////////
	    // Wait until the Resaltar function
	    // terminates (Insert will receive noti-
	    // fication of this via functionFinished)

	    bloqueado = true;
	  }
	}
	else {

	  actualizarInfo = "Nodo : " + trapseNode.getValue() + " Encontrado";

	  setChanged();
	  notifyObservers((Object) actualizarInfo);

	  setChanged();
	  notifyObservers((Object) trapseNode);

	  ////////////////////////////////////////
	  // Nothing else to do, so indicate done.

	  terminado = true;
	}
      }
    }
  }
}
