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


/*
 *      Purpose: The main program of the applet
 */
public class BubbleSort extends Applet {
  public void init() {
   setLayout(new BorderLayout());
   BTextPanel WritingArea = new BTextPanel();
   BSortPanel DrawingArea = new BSortPanel();
   BMainPanel MainArea = new BMainPanel(DrawingArea, WritingArea);
   add("Center", MainArea);
   add("North", new BControlPanel(MainArea, this));

  }
}



/*
 *      Purpose: The container panel for the whole applet
 */
class BMainPanel extends Panel {
  public BSortPanel panel1;
  public BTextPanel panel2;

  public BMainPanel(BSortPanel p, BTextPanel t) {
   panel1 = p;
   panel2 = t;

   setLayout(new GridLayout(2, 1));	/* 2 rows, 1 column */
   add(p);
   add(t);
  }

}



/*
 *      Purpose: Drawing the text description   
 */
class BTextPanel extends Panel {
  private int TOPMARGIN=50;
  private int LEFTMARGIN=30;

  public boolean AnimationNext[] = new boolean[15];
  public int NextStep=0;

  private Font f;
  private String Description[][] = new String[15][5];

  public BTextPanel() {
   setBackground(new Color(255, 248, 220));	/* set background as cornsilk */

   f  = new Font("Helvetica", Font.PLAIN, 16);


   Description[0][0] = "Compare the first two values. If the second is";
   Description[0][1] = "smaller, exchange it. Since the first value (3)";
   Description[0][2] = "is smaller than the second value (10), we don't";
   Description[0][3] = "need to exchange this time.";
   Description[0][4] = "";
   AnimationNext[0] = false;

   Description[1][0] = "Next, compare the second and third values, ex-";
   Description[1][1] = "changing them if the third is smaller. This time";
   Description[1][2] = "we need to do the exchange because 4 is smaller"; 
   Description[1][3] = "than 10.";
   Description[1][4] = "";
   AnimationNext[1] = true;

   Description[2][0] = "Continue to compare the third and fourth values,";
   Description[2][1] = "exchanging them if the fourth is smaller. This time";
   Description[2][2] = "we need to do the exchange because 6 is smaller"; 
   Description[2][3] = "than 10.";
   Description[2][4] = "";
   AnimationNext[2] = true;

   Description[3][0] = "Then compare (and possibly exchange) the third ";
   Description[3][1] = "and fourth values, the fourth and fifth, etc., until";
   Description[3][2] = "you reach the end of the array.";
   Description[3][3] = "";
   Description[3][4] = "";
   AnimationNext[3] = true;

   Description[4][0] = "Note that the largest value in the array ends up";
   Description[4][1] = "stored in the last position.";
   Description[4][2] = "";
   Description[4][3] = "";
   Description[4][4] = "";
   AnimationNext[4] = false;

   Description[5][0] = "Now, go back to the beginning of the array and";
   Description[5][1] = "repeat the comparing and exchanging values";
   Description[5][2] = "again. However, since the largest value is already";
   Description[5][3] = "at the last position, we need not compare the final";
   Description[5][4] = "value.";
   AnimationNext[5] = true;

   Description[6][0] = "Repeat the process of comparsion and exchange";
   Description[6][1] = "without bothering the final two values";
   Description[6][2] = "";
   Description[6][3] = "";
   Description[6][4] = "";
   AnimationNext[6] = true;

   Description[7][0] = "An ordered list with three elements is formed";
   Description[7][1] = "on the right (blue part). These values will not be";
   Description[7][2] = "changed further because they are already the ";
   Description[7][3] = "largest three values in the array.";
   Description[7][4] = "";
   AnimationNext[7] = false;

   Description[8][0] = "Repeat the process of comparison and exchange ";
   Description[8][1] = "without bothering the blue part of the array. At the";
   Description[8][2] = "end of each iteraion, the largest value in the black";
   Description[8][3] = "part of the array 'bubbles' up and become a blue ";
   Description[8][4] = "element.";
   AnimationNext[8] = true;

   Description[9][0] = "The array will become sorted when we get to the";
   Description[9][1] = "point comparing only the first two values";
   Description[9][2] = "";
   Description[9][3] = "";
   Description[9][4] = "";
   AnimationNext[9] = true;

   Description[10][0] = "The whole array is sorted now";
   Description[10][1] = "";
   Description[10][2] = "";
   Description[10][3] = "";
   Description[10][4] = "";
   AnimationNext[10] = true;

  }

  public void paint(Graphics g) {
   g.drawRect(0, 0, size().width-1, size().height-1);

   g.setFont(f);
   for (int i=0; i<5; i++) {
    g.drawString(Description[NextStep][i], LEFTMARGIN, TOPMARGIN+18*i); 
   }
  }


  public void Next() {
   NextStep++;
   repaint();
  }


  /*
   *    Purpose: reset this panel to the begining situation
   */
  public void reset() {
   NextStep=0;
   repaint();
  }

}


/*
 *      Purpose: the control panel
 */
class BControlPanel extends Panel {
  BMainPanel MainArea;
  Button b1, b2, b3, bsound;
  Checkbox cb_sound;
  Applet applet;
  boolean voice=false;
  AudioClip ac=null;

  String sound[] = new String[11];

  public BControlPanel(BMainPanel m, Applet app) {
   MainArea = m;
   applet = app;

   sound[0] = "sound/bubble1.au";
   sound[1] = "sound/bubble2.au";
   sound[2] = "sound/bubble3.au";
   sound[3] = "sound/bubble4.au";
   sound[4] = "sound/bubble5.au";
   sound[5] = "sound/bubble6.au";
   sound[6] = "sound/bubble7.au";
   sound[7] = "sound/bubble8.au";
   sound[8] = "sound/bubble9.au";
   sound[9] = "sound/bubble10.au";
   sound[10] = "sound/bubble11.au";

   setLayout(new FlowLayout(FlowLayout.LEFT));
   setBackground(Color.lightGray);
   b1 = new Button("Start Animation");
   b2 = new Button("  Next  ");
   reset();
   add(b1);
   add(b2);

   cb_sound = new Checkbox("Voice Description");
   cb_sound.setState(false);
   add(cb_sound);
  }


  /*
   *    build in function to control events
   */
  public boolean action(Event e, Object arg) {
   
   if (e.target instanceof Button) {
     String str = ((Button)(e.target)).getLabel();
     if (str.equals("Start Animation")) {
	b1.disable();
	cb_sound.disable();
	MainArea.panel1.Next();
	cb_sound.enable();
	b2.enable();
     } else if (str.equals("  Next  ")) {
	b2.disable();
	MainArea.panel2.Next();
        if (voice) {
/*        applet.play(applet.getCodeBase(), sound[MainArea.panel2.NextStep]); */
          if (ac != null) ac.stop();
          ac = applet.getAudioClip(applet.getCodeBase(), sound[MainArea.panel2.NextStep]);
          ac.play();
        }

	switch (MainArea.panel2.NextStep) {
	  case 1:
	  case 2:
	  case 3:
	  case 10:
		MainArea.panel1.Next();
		break;

	  default:
	}

	if (MainArea.panel2.AnimationNext[MainArea.panel2.NextStep]) {
	   if (MainArea.panel2.NextStep < 10) 
		b1.enable();
	   else {
		b2.setLabel("Restart");
		b2.enable();
	   }
	} else {
	   b2.enable();
	}
     } else if (str.equals("Restart")) {
	MainArea.panel1.reset();
	MainArea.panel2.reset();
        b2.setLabel("  Next  ");
	reset();
     } else if (str.equals("Voice Description")) {
        System.out.println(applet.getCodeBase());
        applet.play(applet.getCodeBase(), sound[MainArea.panel2.NextStep]);
     } else if (str.equals("Disable Voice")) {
        voice = false;
        bsound.setLabel("Enable Voice");
     } else if (str.equals("Enable Voice")) {
        voice = true;
        bsound.setLabel("Disable Voice");
        applet.play(applet.getCodeBase(), sound[MainArea.panel2.NextStep]);
     }


   } else if (e.target instanceof Checkbox) {
     Checkbox cb = (Checkbox)e.target;
     String str = cb.getLabel();
     
     if (str.equals("Voice Description")) {
       if (cb.getState()) {
         voice = true;
/*         applet.play(applet.getCodeBase(), sound[MainArea.panel2.NextStep]); 
*/
         if (ac != null) ac.stop();
         ac = applet.getAudioClip(applet.getCodeBase(), sound[MainArea.panel2.NextStep]);
         ac.play();
       } else {
         voice = false;
         ac.stop();
       }
     }
 
   }


   return true;
  }


  /*
   *    Purpose: reset this panel to the initial situation
   */
  public void reset() {
   b1.disable();
   b2.enable();
  }

}	/* End Class BControlPanel */
