import java.lang.*;
import java.awt.*;
import java.applet.*;


/*
 *	Purpose: the drawing area of the applet
 */
class BSortPanel extends Canvas {
  private int LEFTMARGIN=50;
  private int TOPMARGIN=80;
  private int BOXSIZE=30;
  public int NextStep=0;

  private int UP=-35;
  private int NORMAL=0;
  private int DOWN=35;

  private Font f;
  private long PAUSE_TIME=300;

  private int I=-1;
  private int J=-1;
  private int DontNeedCompare;

  public int arr[];
  public int posx[];
  public int posy[];

  public int blue=10;
  public int current=-1;
  private boolean Erase=false;

  private Thread kicker;


  public BSortPanel() {
   /* set background as White */
   setBackground(Color.white);

   int a[] = new int[10];
   arr = a;

   int px[] = new int[10];
   posx = px;

   int py[] = new int[10];
   posy = py;

   f = new Font("Courier", Font.PLAIN, 14);
   reset();
  }

  /*
   *	Purpose: reset to the begining condition
   */
  public void reset()
  {
   NextStep = 0;
   blue = 10;
   current = -2;
   DontNeedCompare = 0;

   for (int i=0; i<10; i++) {
        posx[i] = i;
        posy[i] = NORMAL;
   }

   arr[0] = 3;  arr[1] = 10;  arr[2] = 4;  arr[3] = 6;  arr[4] = 8;
   arr[5] = 9;  arr[6] = 7;   arr[7] = 2;  arr[8] = 1;  arr[9] = 5;

   repaint();
  }	/* End Method reset() */


  /*
   *	Parameters, Purpose: build in function
   */
  public void paint(Graphics g) {

   System.out.println("paint!");
   if (I<0) g.clearRect(0, 0, size().width-1, size().height-1);
   g.drawRect(0, 0, size().width-1, size().height-1);

   g.setFont(f);

   if (I>=0) {
     if (Erase) {
	EraseElement(g, I, posx[I], posy[I]); 
	EraseElement(g, J, posx[J], posy[J]);
	return;
     } else {
	if (posy[I] == UP) g.setColor(Color.red);
	else g.setColor(Color.black);

	DrawElement(g, I, posx[I], posy[I]); 

	if (posy[J] == DOWN) g.setColor(Color.red);
	else g.setColor(Color.black);

	if (J >= blue)
	  g.setColor(Color.blue);
	DrawElement(g, J, posx[J], posy[J]);
	return;
     }
   }

   for (int i=0; i<10; i++) {
    if (i >= blue && posy[i] == NORMAL)
	g.setColor(Color.blue);
    else
	g.setColor(Color.black);

    if (i == DontNeedCompare || i == DontNeedCompare+1) {
	g.setColor(Color.red);
	if (i==DontNeedCompare) DrawNotice(g, i);
    }
    DrawElement(g, i, posx[i], posy[i]);
   }

  }


  /*
   *	Parameters, Purpose: build in function
   */
  public void update(Graphics g) { 
	System.out.println("update!"); 
	this.paint(g); 
  }

  /*
   *    Parameter: g - Graphics Object
   *               index - index of the element need to be erased
   *               positionX, positionY - current position of this element
   *    Purpose: Erase the specified element
   */
  public void EraseElement(Graphics g, int index, int positionX, int positionY)
  {

   g.clearRect(LEFTMARGIN+(BOXSIZE+1)*positionX, TOPMARGIN+positionY,
                BOXSIZE+1, BOXSIZE+1);
  }


  /*
   *    Parameter: g - Graphics Object
   *               index - index of the element need to be erased
   *               positionX, positionY - current position of this element
   *    Purpose: Draw the specified element
   */
  public void DrawElement(Graphics g, int index, int positionX, int positionY) {

   if (index == current || index == current+1) {
     g.setColor(Color.red);
     g.drawOval(LEFTMARGIN+(BOXSIZE+1)*positionX+2, TOPMARGIN+positionY+2, 
                BOXSIZE-4, BOXSIZE-4);
   } else {
     g.drawRect(LEFTMARGIN+(BOXSIZE+1)*positionX, TOPMARGIN+positionY, 
                BOXSIZE, BOXSIZE);
   }

   g.drawString(Integer.toString(arr[index]),
         LEFTMARGIN+(BOXSIZE+1)*positionX+8, TOPMARGIN+20+positionY);
  }


  /*
   *	Purpose: Draw the "don't need to swap" notice above the index-th element
   */
  public void DrawNotice(Graphics g, int index) {
   g.drawString("Don't need", LEFTMARGIN+(BOXSIZE+1)*index-5, TOPMARGIN-20);
   g.drawString("to swap", LEFTMARGIN+(BOXSIZE+1)*index-5, TOPMARGIN-5);
  }


  /*
   *	Parameter: i - the first element of the two elements which are currently
   *                   compared
   *    Purpose: Highlight the elements currently compared
   */
  public void DrawCompare(int i) {

   try {
       Thread.sleep(PAUSE_TIME);
   } catch (InterruptedException e1){
   }

   DontNeedCompare = i;
   paint(this.getGraphics());
   getToolkit().sync();

   try {
       Thread.sleep(PAUSE_TIME);
   } catch (InterruptedException e1){
   }

  }	/* End Method DrawCompare() */


  /*
   *	Parameters: i, j - the indices of the two elements need to be swapped
   *	Purpose: Do the swap and draw the swap
   */
  public void Swap(int i, int j) {

   /* Wait a while before really start the swap */
   try {
       Thread.sleep(PAUSE_TIME);
   } catch (InterruptedException e1){
   }

   if (i==j) {
     blue--;
     I=J=i;
     paint(this.getGraphics());
     getToolkit().sync();
     try {
       Thread.sleep(PAUSE_TIME);
     } catch (InterruptedException e1){
     }
     I=J=-1;
     return;
   }

   I=i; J=j;

   Erase=true;
   paint(this.getGraphics()); 
   getToolkit().sync();
   posy[i] = UP;
   posy[j] = DOWN;
   Erase=false;
   paint(this.getGraphics()); 
   getToolkit().sync();
   try {
     Thread.sleep(PAUSE_TIME);
   } catch (InterruptedException e1){
   }

   for (int k=0; k<j-i; k++) {
     Erase=true;
     paint(this.getGraphics()); 
     getToolkit().sync();
     posx[i] = posx[i] + 1;
     posx[j] = posx[j] - 1;
    
     Erase=false;
     paint(this.getGraphics()); 
     getToolkit().sync();

     try {
       Thread.sleep(PAUSE_TIME);
     } catch (InterruptedException e2){
     }
   }


   Erase=true;
   paint(this.getGraphics());
   getToolkit().sync();

   if (j==blue-1) blue--;
   posy[i] = NORMAL;
   posy[j] = NORMAL;

   int tmp = arr[i];
   arr[i] = arr[j];
   arr[j] = tmp;

   posx[i] = i;
   posx[j] = j;

   Erase=false;
   paint(this.getGraphics());
   getToolkit().sync();

   I=J=-1;
  }


  /*
   *	Purpose: Do the animation. executed when the "start animation" button
   *              is pressed
   */
  public void Next() {

   switch (NextStep) {
    case 0:
	DontNeedCompare = -2;
	current = 1;
	repaint();
	break;

    case 1:
	current = -2;
	Swap(1, 2);
	break;

    case 2:
	current = 2;
	repaint();
	break;

    case 3:
	current = -2;
	Swap(2, 3);
	break;

    case 4:
	current = 3;
	repaint();
	break;

    case 5:
	current = -2;
	Swap(3, 4);
	Swap(4, 5);
	Swap(5, 6);
	Swap(6, 7);
	Swap(7, 8);
	Swap(8, 9);
	break;

    case 6:
	DrawCompare(0);
	DrawCompare(-2);
	DrawCompare(1);
	DrawCompare(-2);
	DrawCompare(2);
	DrawCompare(-2);
	DrawCompare(3);
	DrawCompare(-2);
	Swap(4, 5);
	Swap(5, 6);
	Swap(6, 7);
	Swap(7, 8);
	break;

    case 7:
	DrawCompare(0);
	DrawCompare(-2);
	DrawCompare(1);
	DrawCompare(-2);
	DrawCompare(2);
	DrawCompare(-2);
	Swap(3, 4);
	Swap(4, 5);
	Swap(5, 6);
	Swap(6, 7);
	break;

    case 8:
	DrawCompare(0);
	DrawCompare(-2);
	DrawCompare(1);
	DrawCompare(-2);
	DrawCompare(2);
	DrawCompare(-2);
	Swap(3, 4);
	Swap(4, 5);
	Swap(5, 6);
	
	DrawCompare(0);
	DrawCompare(-2);
	DrawCompare(1);
	DrawCompare(-2);
	Swap(2, 3);
	Swap(3, 4);
	Swap(4, 5);

	DrawCompare(0);
	DrawCompare(-2);
	Swap(1, 2);
	Swap(2, 3);
	DrawCompare(3);
	DrawCompare(-2);
	Swap(4, 4);
	break;

    case 9:
	Swap(0, 1);
	Swap(1, 2);
	DrawCompare(2);
	DrawCompare(-2);
	Swap(3, 3);

	Swap(0, 1);
	DrawCompare(1);
	DrawCompare(-2);
	Swap(2, 2);

	DrawCompare(0);
	DrawCompare(-2);
	Swap(1, 1);
	break;

    case 10:
	blue--;
	repaint();
	break;

    default:
   }

   NextStep++;
  }	/* End Method Next() */

}

