package elaprendiz.estructuras.funciones;

import elaprendiz.graficos.funciones.Funcion;

import java.awt.Point;

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

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

public class ExtenderArbol extends Funcion implements Observer {

  boolean bloqueado = false;

  public ExtenderArbol(LienzoBinario canvas) {
    int level = canvas.getLevel() - 1;

    int[] values;

    for (int i = 0; i < level; i++) {
      values = canvas.getLevelValues(i);

      if (values[2] == LienzoBinario.LEVEL_ONE) {
	values[0] = 2 * values[0];
	values[1] = (int) (values[1] / 2);
	values[2] = LienzoBinario.LEVEL_TWO;
      }
      else {
	values[0] = 2 * values[0];

	if (values[2] == LienzoBinario.LEVEL_TWO)
	  values[2] = LienzoBinario.LEVEL_THREE;
      }

      canvas.setLevelValues(i, values);
    }

    ArbolNodo parent;
    ArbolNodo leftChild;
    ArbolNodo rightChild;

    int startCheck;
    int endCheck;

    int xMove;
    int yMove;

    boolean functionsRun = false;

    for (int i = 0; i < level; i++) {

      startCheck = (int) Math.pow(2, i);
      endCheck   = (int) Math.pow(2, (i + 1));

      values = canvas.getLevelValues(i);

      for (int j = startCheck; j < endCheck; j++) {
	if ( (parent = canvas.getNodeAtRank(j)) != null) {

	  xMove = (int) (values[0] / 2);
	  yMove = (values[2] == LienzoBinario.LEVEL_TWO) ? values[1] : 0;

	  if ( (leftChild = parent.getLeftChild()) != null) {
	    Funcion mover = new MoverSubArbol(new Point(leftChild.origin().x -
	      xMove, leftChild.origin().y - yMove), leftChild);
	    mover.addObserver(this);

	    canvas.addFunction(mover);

	    functionsRun = true;
	  }

	  if ( (rightChild = parent.getRightChild()) != null) {
	    Funcion mover = new MoverSubArbol(new Point(rightChild.origin().x +
	      xMove, rightChild.origin().y - yMove), rightChild);
	    mover.addObserver(this);

	    canvas.addFunction(mover);

	    functionsRun = true;
	  }
	}
      }
    }

    if (functionsRun)
      bloqueado = true;
  }

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

  public void performFuncion() {
    if (bloqueado == false) {
      terminado = true;
    }
  }
}
