import java.awt.*;
import java.io.*;
import java.net.*;
import java.util.*;

public class bardCode extends java.applet.Applet  implements Runnable{
 Thread t; 
 Image buf1;
 Image buf2;
 boolean buf,isDown =false;
 boolean noAdjust = true;
 int x = 0;
 int file = 0; 
 Hashtable code128;
 Font font;

  public void init(){
       setBackground(Color.white);
       font = new Font("Helvetica",Font.PLAIN,12);
       buf1 = createImage(640,80);
       buf2 = createImage(640,80);
       code128 = new Hashtable();
       code128.put(" ", "212222");
       code128.put("!", "222122");
       code128.put("\"","222221");
       code128.put("#", "121223");
       code128.put("$", "121322");
       code128.put("%", "131222");
       code128.put("&", "122213");
       code128.put("'", "122312");
       code128.put("(", "132212");
       code128.put(")", "221213");
       code128.put("*", "221312");
       code128.put("+", "231212");
       code128.put(",", "112232");
       code128.put("-", "122132");
       code128.put(".", "122231");
       code128.put("/", "113222");
       code128.put("0", "123122");
       code128.put("1", "123221");
       code128.put("2", "223211");
       code128.put("3", "221132");
       code128.put("4", "221231");
       code128.put("5", "213212");
       code128.put("6", "223112");
       code128.put("7", "312131");
       code128.put("8", "311222");
       code128.put("9", "321122");
       code128.put(":", "321221");
       code128.put(";", "312212");
       code128.put("<", "322112");
       code128.put("=", "322211");
       code128.put(">", "212123");
       code128.put("?", "212321");
       code128.put("@", "232121");
       code128.put("A", "111323");
       code128.put("B", "131123");
       code128.put("C", "131321");
       code128.put("D", "112313");
       code128.put("E", "132113");
       code128.put("F", "132311");
       code128.put("G", "211313");
       code128.put("H", "231113");
       code128.put("I", "231311");
       code128.put("J", "112133");
       code128.put("K", "112331");
       code128.put("L", "132131");
       code128.put("M", "113123");
       code128.put("N", "113321");
       code128.put("O", "133121");
       code128.put("P", "313121");
       code128.put("Q", "211331");
       code128.put("R", "231131");
       code128.put("S", "213113");
       code128.put("T", "213311");
       code128.put("U", "213131");
       code128.put("V", "311123");
       code128.put("W", "311321");
       code128.put("X", "331121");
       code128.put("Y", "312113");
       code128.put("Z", "312311");
       code128.put("[", "332111");
       code128.put("\\", "314111");
       code128.put("]", "221411");
       code128.put("^", "431111");
       code128.put("_", "111224");
       code128.put("`", "111422");
       code128.put("a", "121124");
       code128.put("b", "121421");
       code128.put("c", "141122");
       code128.put("d", "141221");
       code128.put("e", "112214");
       code128.put("f", "112412");
       code128.put("g", "122114");
       code128.put("h", "122411");
       code128.put("i", "142112");
       code128.put("j", "142211");
       code128.put("k", "241211");
       code128.put("l", "221114");
       code128.put("m", "413111");
       code128.put("n", "241112");
       code128.put("o", "134111");
       code128.put("p", "111242");
       code128.put("q", "121142");
       code128.put("r", "121241");
       code128.put("s", "114212");
       code128.put("t", "124112");
       code128.put("u", "124211");
       code128.put("v", "411212");
       code128.put("w", "421112");
       code128.put("x", "421211");
       code128.put("y", "212141");
       code128.put("z", "214121");
       code128.put("{", "412121");
       code128.put(" ", "111143");
       code128.put("}", "111341");
       code128.put("~", "131141");
       code128.put("DEL", "114113");
       code128.put("\\", "114311");
       code128.put("|", "411111");
       code128.put("SHIFT", "411311");
       code128.put("CODE C", "113141");
       code128.put("CODE B", "114131");
       code128.put("FNC 4", "311141");
       code128.put("FNC 1", "411131");
       code128.put("StartA", "211412");
       code128.put("StartB", "211214");
       code128.put("StartC", "211232");
       code128.put("Stop","2331112");  
  }

  public void start(){
     t = new Thread(this);
     t.start();
  }
  public void stop(){
      if(t!=null) t.stop();
      t = null;
  }

  public void run(){
     URL url;
     DataInputStream in=null;
     Graphics bg=null;
     controls("Buffering...");
     String str = "(Buffering...)";
     while(file<924){
     // long start = System.currentTimeMillis(); 
	try{
	    noAdjust=true;
	    url = new URL("http://"+getDocumentBase().getHost()+"/bardcode/docs/play.php?num="+(new Integer(file)).toString());	
            in  = new DataInputStream(new BufferedInputStream(url.openStream()));
	    if(in!=null) str = in.readLine();
            controls("Now playing: "+str.substring(0,str.length()-5));
	    repaint();
	    while((str=in.readLine())!=null && noAdjust){
	        bg = buf?buf1.getGraphics():buf2.getGraphics();
	        if(str.length()>1){
			if(bg!=null){
			    drawBar(str,bg);
			    repaint(0,0,640,45);
                   	    bg.dispose();
                        }
                }
		t.sleep(100);
	    }
	    if(in!=null) in.close();
	}catch(Exception e){
	    finis();
 	    //e.printStackTrace();
	}
	//System.out.println(System.currentTimeMillis()-start);
	file++;
     }
     finis();
  }
  public void  finis(){
	    Graphics g = getGraphics();
	    if(g!=null && file>=924){
	      g.setColor(Color.white);
	      g.fillRect(0,45,640,35);
	      g.setColor(Color.black);
              g.setFont(font);
              g.drawString("Finis", 1,61);
              g.dispose();
             }
  }
  public void update(Graphics g){
	paint(g);
  }
  public void paint(Graphics g){
	g.drawImage(buf?buf1:buf2,0,0,null);
        buf=!buf;
  }
  public boolean handleEvent(Event e){
 	switch(e.id){
		case Event.GOT_FOCUS:
		case Event.SCROLL_ABSOLUTE:
		case Event.SCROLL_LINE_DOWN:
		case Event.SCROLL_LINE_UP:
		case Event.SCROLL_PAGE_DOWN:
		case Event.SCROLL_PAGE_UP:
		case Event.WINDOW_DEICONIFY:
		case Event.WINDOW_EXPOSE:
		case Event.WINDOW_MOVED:
            	controls("Buffering...");
		break;

		case Event.MOUSE_DOWN:
       		if(e.x>0&&e.x<468&&e.y>65){
	    		isDown = true;
            		file = Math.max(0,Math.min(923,e.x*2));
	    		noAdjust=false;
       		}
		break;

		case Event.MOUSE_DRAG:
       		if(e.x>0&&e.x<468&&isDown){
            		file = Math.max(0,Math.min(923,e.x*2));
            		controls("Buffering...");
	    		noAdjust=false;
		}
		break;

		case Event.MOUSE_UP:
       		if(isDown){
	 		file = Math.max(0,Math.min(923,e.x*2));
         		isDown = false;
			if(t==null || !t.isAlive()) start();
		}
		drawBar("blowme",buf2.getGraphics());
		drawBar("blowme",buf1.getGraphics());
		repaint();
		break;
	}
	return true;
  }

  public void controls(String s){
	if(s==null) return;
     Graphics g = buf1.getGraphics();
       if(g!=null){
	      g.setColor(Color.white);
	      g.fillRect(0,45,640,35);
	      g.setColor(Color.black);
	      g.drawRect(0,67,470,12);
	      g.drawRect(1+file/2,68,8,10);
	      g.setColor(Color.gray);
	      g.fill3DRect(2+file/2,69,6,8,true);
              g.setFont(font);
              g.drawString(s, 1,61);
              g.dispose();
       }
       g = buf2.getGraphics();
       if(g!=null){
	      g.setColor(Color.white);
	      g.fillRect(0,45,640,35);
	      g.setColor(Color.black);
	      g.drawRect(0,67,470,12);
	      g.drawRect(1+file/2,68,8,10);
	      g.setColor(Color.gray);
	      g.fill3DRect(2+file/2,69,6,8,true);
              g.setFont(font);
              g.drawString(s, 1,61);
              g.dispose();
       }
     repaint();	
  }

 
public void drawBar(String word, Graphics g){
  boolean bar = true;
  String stripes;
  int tot = 104;
  int cur;
  int wid = (word.length()*11) + 25;
 
  if(g!=null) g.setColor(Color.white);
  if(g!=null) g.fillRect(0,0,640,45);
  if(g!=null) g.setColor(Color.black);
 
  // START PATTERN
  if(g!=null) g.fillRect(0,0,2,45);
  if(g!=null) g.fillRect(3,0,1,45);
  if(g!=null) g.fillRect(6,0,1,45);
  x = 11;
 
  for(int i=0; i<word.length(); i++){
    String c = word.substring(i,i+1);
     char ival = word.charAt(i);
        tot += ((i+1) * (int)ival);
        stripes = (String)code128.get(c);
	bar = true;
  	for(int j=0; j<6;j++){
      	    try{
       		cur = Integer.parseInt(stripes.substring(j,j+1));
         	if(bar) g.fillRect(x,0,cur,45);
                x+=cur;
            }catch(NullPointerException npe){}
       	    bar = !bar;
  	}
  }
 
  // SANITY CHECK CHAR
  stripes = (String)code128.get(codes[tot%103]);
  bar = true;
  for(int j=0;j<6;j++){
      try{
          cur = Integer.parseInt(stripes.substring(j,j+1));
          if(bar) g.fillRect(x,0,cur,45);
          x+=cur;
      }catch(NullPointerException npe){}
      bar = !bar;
  }
 
  // STOP SEQUENCE
  if(g!=null) g.fillRect(x,0,2,45);
  if(g!=null) g.fillRect(x+5,0,3,45);
  if(g!=null) g.fillRect(x+9,0,1,45);
  if(g!=null) g.fillRect(x+11,0,2,45);               
}

String codes[] = { " ", "!", "\"", "#", "$", "%",
"&", "'", "(", ")", "*", "+", ",", "-",
".", "/", "0", "1", "2", "3", "4", "5",
"6", "7", "8", "9", ":", ";", "<", "=",
">", "?", "@", "A", "B", "C", "D", "E",
"F", "G", "H", "I", "J", "K", "L", "M",
"N", "O", "P", "Q", "R", "S", "T", "U",
"V", "W", "X", "Y", "Z", "[", "\\", "]",
"^", "_", "`", "a", "b", "c", "d", "e",
"f", "g", "h", "i", "j", "k", "l", "m",
"n", "o", "p", "q", "r", "s", "t", "u",
"v", "w", "x", "y", "z", "{", " ", "}",
"~", "DEL", "\\", "|", "SHIFT", "CODE C",
"CODE B", "FNC 4",  "FNC 1", "StartA", "StartB",
"StartC", "Stop" };  

}
