
import java.util.*;
import java.awt.*;

public class DemoApplet extends BufferedApplet
{
   int W = 0, H;
   Font font = new Font("Courier", Font.BOLD, 20);
   Font smallFont = new Font("Courier", Font.BOLD, 14);
   int shiftState = 0;
   boolean control = false;
   Color c0 = new Color(0,192,0);
   Color c1 = new Color(255,192,0);
   Color c2 = new Color(255,0,0);
   AlphaDraw z = new AlphaDraw();
   Graphics g;
   TextEditor text = new TextEditor();
   int px, py, pr;

   public void render(Graphics g) {
      this.g = g;
      if (W == 0) {
         W = bounds().width;
         H = bounds().height;
	 text.setBounds(W, H);

	 text.enterText("Now is the time\n");
	 text.enterText("for all good men\n");
	 text.enterText("to come to the aid\n");
	 text.enterText("of their party.\n");

	 px = 11*W/16;
	 py = 11*H/16;
	 pr = W/4;
      }

      g.setColor(Color.white);
      g.fillRect(0,0,W,H);

      drawPattern(g, px, py, pr);

      if (pattern != null)
         drawPattern(g);

      drawSquiggle(xy, n, false);

      g.setFont(font);

      text.render(g);
   }

   void drawSquiggle(int xy[], int n, boolean isArrow) {
      if (n > 2) {
         g.setColor(Color.black);
	 double Dx = xy[2]-xy[0], Dy = xy[3]-xy[1];
         for (int i = 0 ; i < n-2 ; i += 2) {
            g.drawLine(xy[i],xy[i+1],xy[i+2],xy[i+3]);
	    if (isArrow) {
	       Dx = .5 * Dx + .5 * (xy[i+2] - xy[i  ]);
	       Dy = .5 * Dy + .5 * (xy[i+3] - xy[i+1]);
	       if (i == n-4) {
	          double R = Math.sqrt(Dx*Dx + Dy*Dy);
	          int dx = (int)(8 * Dx / R);
	          int dy = (int)(8 * Dy / R);
	          g.drawLine(xy[i]+dy, xy[i+1]-dx, xy[i+2], xy[i+3]);
	          g.drawLine(xy[i]-dy, xy[i+1]+dx, xy[i+2], xy[i+3]);
               }
            }
         }
      }
   }

   int xy[] = new int[1000];
   int n = 0;

   boolean isSelecting = false;
   int xDown, yDown;

   public boolean mouseDown(Event e, int x, int y) {
      n = 0;
      if (text.isOverText(x,y)) {
         isSelecting = true;
	 xDown = x;
	 yDown = y;
         text.select(xDown, yDown, x, y);
      }
      else {
         isSelecting = false;
         xy[n++] = x;
         xy[n++] = y;
      }
      pattern = null;
      damage = true;
      return true;
   }
   public boolean mouseDrag(Event e, int x, int y) {
      if (isSelecting) {
         text.select(xDown, yDown, x, y);
      }
      else {
         xy[n++] = x;
         xy[n++] = y;
      }
      damage = true;
      return true;
   }
   public boolean mouseUp(Event e, int x, int y) {
      int c = 0;

      if (isSelecting) {
         if (! text.hasSelection())
	    text.placeCursor(xDown,yDown);
         isSelecting = false;
	 n = 0;
	 damage = true;
	 return true;
      }

      xy[n++] = x;
      xy[n++] = y;
      if (n >= 6) {
         c = z.recognize(xy, n);
         if (control)
	    c = c - ('a'-1);
         control = false;
      }

      switch (c) {
      case -1:              // DO NOTHING
         break;
      case 0:               // TOGGLE NUMERIC KEYPAD
         z.toggleNumeric();
         break;
      case AlphaDraw.SHIFT: // SHIFT
         shiftState = (shiftState + 1) % 3;
         break;
      case AlphaDraw.CNTRL: // CONTROL
	 control = true;
         break;
      case 'C' - '@':       // CONTROL C
         text.copy();
         break;
      case 'V' - '@':       // CONTROL V
         text.paste();
         break;
      case 'X' - '@':       // CONTROL X
         text.cut();
         break;
      case AlphaDraw.SEND:  // SEND
         System.out.println("SEND");
         break;
      case AlphaDraw.END:   // END
         System.out.println("END");
         break;
      default:
	 if (c == '\b' && text.hasSelection())
	    text.cut();
         else
	    enterTextChar(c);
         break;
      }

      n = 0;
      damage = true;
      return true;
   }

   void enterTextChar(int c) {
      text.enterText("" + (char)(shiftState != 0 ? z.shift(c) : c));
      if (shiftState == 1)
         shiftState = 0;
      damage = true;
   }

   public boolean keyUp(Event e, int key) {
      switch (key) {
      case 'N'-'@': // CONTROL-N
	 z.toggleHasNumbers();
	 damage = true;
	 break;
      default:
         simulateTextChar(key);
	 break;
      }
      return true;
   }

   double[] pattern = null;

   void simulateTextChar(int c) {
      pattern = z.getPattern("" + (char)c);
      System.out.println("pattern = " + pattern);
      enterTextChar(c);
   }

   Random R = new Random();
   int pxy[] = new int[1000];
   void drawPattern(Graphics g) {
      int n = pattern.length / 2;
      double x = 0, y = 0;
      for (int i = 0 ; i < n ; i++) {
	 pxy[2*i  ] = (int)(px - pr/4 + pr/2 * pattern[i  ] + x);
	 pxy[2*i+1] = (int)(py - pr/4 + pr/2 * pattern[i+n] + y);
	 x += .02 * (R.nextInt() % 100);
	 y += .02 * (R.nextInt() % 100);
      }
      drawSquiggle(pxy, 2 * n, true);
   }

   Color patternTextColor = new Color(128,160,255);
   Color patternLineColor = new Color(160,200,255);
   void drawPattern(Graphics g, int x, int y, int r) {
      int J[] = { 1,0,-1,  1,0,-1,  1,-1};
      int K[] = { 0,0, 0,  1,1, 1,  2, 2};
      double p[] = {
                      0,8,-1.5,8  , 0,6, 0,8  , 0,8, 1.5,8  ,
                      0,8,-1.5,6.5, 0,8, 0,6.5, 0,8, 1.5,6.5,
                     -1,7,-1,5.5,         1,7,1,5.5,
                   };
      for (int i = 0 ; i < 8 ; i++) {
         double theta = Math.PI * (5 - i) / 4;
         double cos = r * Math.cos(theta), sin = r * Math.sin(theta);
   
         int x0 = 0, y0 = 0;
            for (int m = 0 ; m < p.length ; m += 2) {
               int x1 = x + (int)( cos * p[m] + sin * p[m+1]) / 8;
               int y1 = y + (int)(-sin * p[m] + cos * p[m+1]) / 8;
            if (m % 4 == 2) {
               if (K[m/4] < 2) {
                  g.setColor(patternLineColor);
                  g.drawLine(x0,y0, x1,y1);
                  g.setColor(patternTextColor);
               }
               else
                  g.setColor(patternLineColor);
               int c = z.map(i, J[m/4], K[m/4]);
               if (c == '?')
                  continue;
               if (shiftState != 0)
                  c = z.shift(c);
               String s = "" + (char)c;
               Font f = smallFont;
               switch (c) {
               case AlphaDraw.SHIFT:
	          switch (shiftState) {
		     case 0: s = "CAP"; break;
		     case 1: s = "SL"; break;
		     case 2: s = "SD"; break;
		  } 
                  break;
	       case 'C'-'@': s = "COPY";break;
	       case 'V'-'@': s = "PASTE";break;
	       case 'X'-'@': s = "CUT";break;
               case   27   : s = "ESC";break;
               case ' '    : s = "SP"; break;
               case '\b'   : s = "BS"; break;
               case '\t'   : s = "TAB";break;
               case '\n'   : s = "NL"; break;
               case 1004   : s = "UA"; break;
               case 1005   : s = "DA"; break;
               case 1006   : s = "LA"; break;
               case 1007   : s = "RA"; break;
               case AlphaDraw.SEND : s = "SND";break;
               case AlphaDraw.END  : s = "END";break;
               case AlphaDraw.CNTRL: s = "CTL";break;
               default: f = font; break;
               }
               g.setFont(f);
               g.drawString(s, x1 - text.stringWidth(g,s)/2, y1+5);
            }
            x0 = x1;
            y0 = y1;
            }
      }
   }
}


