import java.awt.*;
import java.applet.*;

/*
 *
 * HeapCanvas
 *
 */
class HeapCanvas extends Canvas
{
  final static int MAXHEAP = 100;
  final static int RWSIZE = 50;
  final static int CLSIZE = 600;

  Hsort theApplet;
  int insertHilite = -1;
  int fillHilite = -1;
  int nodeHilite = -1;
  Color colorHilite = Color.red;
  Color nodeColorHilite = Color.blue;
  Color fillColor = Color.yellow;

  public HeapCanvas(int x, int y, Hsort theApplet)
  {
    this.theApplet = theApplet;
    resize(x,y);
  }

  public void paint(Graphics g)
  {
    drawHeap(theApplet.heap, g);
  }

  public void drawHeap(int[] heap, Graphics g)
  {
    Point[] coords = new Point[heap.length];
    for (int i = 0; heap[i] != -1; i++) {
      Point p = coords[i] = nodePoint(i);
      if (nodeHilite == i) g.setColor(nodeColorHilite);
      else if (insertHilite == i || HeapAction.parent(insertHilite) == i)
	g.setColor(colorHilite);
      drawNode(heap[i], p, g, (fillHilite == i));
      g.setColor(Color.black);
      if (i == 0) continue;
      if (insertHilite == i)	g.setColor(colorHilite);
      Point pp = coords[((i+1)/2) - 1];
      g.drawLine(p.x, p.y-RADIUS, pp.x, pp.y+RADIUS);
      g.setColor(Color.black);
    }
    colorHilite = Color.red;
  }

  final static int RADIUS = 15;
  public void drawNode(int val, Point p, Graphics g, boolean mode)
  {
    if (mode) {
      Color hold = g.getColor();
      g.setColor(fillColor);
      g.fillOval(p.x-RADIUS, p.y-RADIUS, 2*RADIUS, 2*RADIUS);
      g.setColor(hold);
    }
    g.drawOval(p.x-RADIUS, p.y-RADIUS, 2*RADIUS, 2*RADIUS);
    String valStr = Integer.toString(val);
    int startx = p.x - (g.getFontMetrics().stringWidth(valStr)/2);
    int starty = p.y + (g.getFontMetrics().getAscent()/2);
    g.drawString(valStr, startx, starty);
  }
  
  static Point nodePoint(int i)
  {
    int row = ilog(i+1);
    int elts = iexp(2,row);
    int col = i - elts + 1;
    int rwlen = CLSIZE/elts;
    return new Point(col*rwlen+(rwlen/2), row*RWSIZE+(RWSIZE/2));
  }

  static int ilog(int n) 
  {
    int ans = 0;
    while (n > 0) {n /= 2; ans++;}
    return ans-1;
  }

  static int iexp(int base, int exp)
  {
    int ans = 1;
    for (int i = 0; i < exp; i++) ans = ans * base;
    return ans;
  }


}

/*
 *
 * HeapButton
 *
 */
class HeapButton extends Button
{
  Hsort theApplet;

  HeapButton(String label, Hsort theApplet)
  {
    super(label);
    this.theApplet = theApplet;
  }

  public boolean action(Event evt, Object what)
  {
    theApplet.repaint();
    theApplet.control.repaint();
    theApplet.message.repaint();
    theApplet.addHeap.disable();
    theApplet.delHeap.disable();
    try {
      switch (((String)what).charAt(0)) {
      case 'H':
	theApplet.theAction.command = HeapAction.BUILDHEAP;
	new Thread(theApplet.theAction).start();
	break;
      case 'A':
	int x = Integer.valueOf(theApplet.addVal.getText()).intValue();
	theApplet.theAction.key = x;
	theApplet.addVal.setText("");
	theApplet.theAction.command = HeapAction.HEAPINSERT;
	new Thread(theApplet.theAction).start();
	break;
      case 'D':
	theApplet.theAction.command = HeapAction.HEAPEXTRACT;
	new Thread(theApplet.theAction).start();
	break;
      }
    } catch (Exception e) {
      theApplet.addHeap.enable();
      if (theApplet.theAction.heapsize() > 0) theApplet.delHeap.enable();
    }
    return true;
  }
}
    /*  theApplet.addVal.setText(Integer.toString(2 * x)); */


