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



/*
 *      Purpose: The main program of the applet
 */
public class BinarySearch extends Applet {
  public void init() {
   setLayout(new BorderLayout());
   BTextPanel WritingArea = new BTextPanel();
   BSearchPanel DrawingArea = new BSearchPanel();
   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 BSearchPanel panel1;
  public BTextPanel panel2;

  public BMainPanel(BSearchPanel 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] = "At first the entire array is unknown but sorted.";
   Description[0][1] = "We try to search the value 10 as an example.";
   Description[0][2] = "";
   Description[0][3] = "";
   Description[0][4] = "";
   AnimationNext[0] = true;

   Description[1][0] = "Divide the array into two parts and examine ";
   Description[1][1] = "the middle value in the array. The index of the";
   Description[1][2] = "middle value is calculated by the formula:";
   Description[1][3] = "(start_index + end_index )/2 (ie. the value";
   Description[1][4] = "with index 4 in this case).";
   AnimationNext[1] = false;

   Description[2][0] = "This value (7) is not the one we searched, ";
   Description[2][1] = "so we need to continue the search.";
   Description[2][2] = "";
   Description[2][3] = "";
   Description[2][4] = "";
   AnimationNext[2] = false;

   Description[3][0] = "Since the array is sorted, the portion before the";
   Description[3][1] = "value 7 will be smaller than 7. Thus, all values";
   Description[3][2] = "in this portion are also smaller than the search ";
   Description[3][3] = "value 10";
   Description[3][4] = "";
   AnimationNext[3] = true;


   Description[4][0] = "Therefore, we can deduce that the search value";
   Description[4][1] = "will not be located at the portion of the array";
   Description[4][2] = "before the value 7.";
   Description[4][3] = "";
   Description[4][4] = "";
   AnimationNext[4] = true;

   Description[5][0] = "Thus, we continue to search the remaining part";
   Description[5][1] = "of the array. We do the same thing: divide this";
   Description[5][2] = "part into two and examine the middle value --";
   Description[5][3] = "the value with index 8.";
   Description[5][4] = "";
   AnimationNext[5] = true;

   Description[6][0] = "By similar argument, we can deduce that the";
   Description[6][1] = "search value is equal to none of the values";
   Description[6][2] = "in the array with index 7-9.";
   Description[6][3] = "";
   Description[6][4] = "";
   AnimationNext[6] = true;

   Description[7][0] = "Repeat the process, this time we examine the ";
   Description[7][1] = "value with index ((6+7) div 2) (ie. 5). After we";
   Description[7][2] = "find that it is not the answer, we finally locate";
   Description[7][3] = "the value need to be searched.";
   Description[7][4] = "";
   AnimationNext[7] = true;

   Description[8][0] = "Notice that the number of values examined is";
   Description[8][1] = "only four. If linear search is used instead, we";
   Description[8][2] = "need to examine seven values.";
   Description[8][3] = "";
   Description[8][4] = "";
   AnimationNext[8] = 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();
  }

  public void reset() {
   NextStep=0;
   repaint();
  }

}


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

  String sound[] = new String[9];

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

   sound[0] = "sound/binary1.au";
   sound[1] = "sound/binary2.au";
   sound[2] = "sound/binary3.au";
   sound[3] = "sound/binary4.au";
   sound[4] = "sound/binary5.au";
   sound[5] = "sound/binary6.au";
   sound[6] = "sound/binary7.au";
   sound[7] = "sound/binary8.au";
   sound[8] = "sound/binary9.au";

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

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


  public boolean action(Event e, Object arg) {
   
   if (e.target instanceof Button) {
     String str = ((Button)(e.target)).getLabel();
     if (str.equals("  Next  ")) {

	b2.disable();
	cb_sound.disable();
	if (MainArea.panel2.AnimationNext[MainArea.panel2.NextStep])
	   MainArea.panel1.Next();
	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();
        }
	cb_sound.enable();
	if (MainArea.panel2.NextStep != 8) 
	  b2.enable();
	else {
	  b2.setLabel("Restart");
	  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;
  }

  public void reset() {
   b2.enable();
  }

}
