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

public class table extends BufferedApplet
{
   // PUBLIC METHODS TO BE OVERRIDDEN

   public void initTable() {
   }

   public void drawTable(Graphics g) {
   }

   public boolean onPickup(int i) {
      return true;
   }

   public boolean onDrop(int i) {
      return true;
   }

   // OTHER PUBLIC METHODS

   public int getTableSize() { return w; }
   public int getPuckSize() { return p; }
   public int getPuckX(int i) { return PX[i]; }
   public int getPuckY(int i) { return PY[i]; }
   public boolean isUp(int i) { return i == puckID; }

   // SUPPORT METHODS

   public void render(Graphics g) {
      if (w == 0) {
         w = bounds().width;
         h = bounds().height;
         p = w / 15; 

         for (int i = 0 ; i < 4 ; i++) {
            double theta = 2 * Math.PI * i / 4;
            PX[i] = (int)(w/2 + w/4 * Math.cos(theta));
            PY[i] = (int)(w/2 + w/4 * Math.sin(theta));
         }

         for (int i = 0 ; i < 50 ; i++) {
            double theta = Math.PI * i / 50;
            CTX[i] = (int)(w/2 + w/2 * Math.cos(theta));
            CTY[i] = (int)(w/2 - w/2 * Math.sin(theta));
            CBX[i] = (int)(w/2 + w/2 * Math.cos(theta));
            CBY[i] = (int)(w/2 + w/2 * Math.sin(theta));
         }
         CTX[50] = 0; CTY[50] = 0;
         CTX[51] = w; CTY[51] = 0;
         CBX[50] = 0; CBY[50] = h;
         CBX[51] = w; CBY[51] = h;

         initTable();
      }

      g.setColor(bgColor);
      g.fillRect(0,0,w,h);

      drawTable(g);

      g.setColor(Color.black);
      g.fillPolygon(CTX, CTY, 52);
      g.fillPolygon(CBX, CBY, 52);

      for (int i = 0 ; i < 4 ; i++)
         if (i != puckID)
            drawPuck(g, i);

      if (puckID >= 0)
         drawPuck(g, puckID);

      animating = true;
   }

   void drawPuck(Graphics g, int i) {
      g.setColor(i == puckID ? lightShadow : Color.black);
      g.fillOval(PX[i] - p/2 + 1, PY[i] - p/2 + 1, p, p);
      g.fillOval(PX[i] - p/2 + 2, PY[i] - p/2 + 2, p, p);

      g.setColor(i == puckID ? lightPuck : Color.gray);
      g.fillOval(PX[i] - p/2, PY[i] - p/2, p, p);

      g.setColor(Color.white);
      switch (i) {
      case 1:
         g.fillOval(PX[i] - p/8, PY[i] - p/8, p/3, p/3);
	 break;
      case 2:
         g.fillOval(PX[i] - p/8, PY[i] - 2*p/9 - p/8, p/3, p/3);
         g.fillOval(PX[i] - p/8, PY[i] + 2*p/9 - p/8, p/3, p/3);
	 break;
      case 3:
         for (int j = 0 ; j < i ; j++) {
            double theta = 2 * Math.PI * j / 3;
            int x = (int)(p/3.7 * Math.cos(theta));
            int y = (int)(p/3.7 * Math.sin(theta));
            g.fillOval(PX[i] + x - p/8, PY[i] + y - p/8, p/3, p/3);
         }
      }
   }

   public boolean mouseDown(Event e, int x, int y) {
      puckID = -1;
      for (int i = 0 ; i < 4 ; i++) {
         int X = x - PX[i];
         int Y = y - PY[i];
         if (X*X + Y*Y < p*p/4) {
            puckID = i;
            onPickup(puckID);
            return true;
         }
      }
      return true;
   }

   public boolean mouseUp(Event e, int x, int y) {
      if (puckID >= 0) {
         onDrop(puckID);
         PX[puckID] = x;
         PY[puckID] = y;
      }
      puckID = -1;
      return true;
   }

   private int w = 0, h, p, puckID = -1;
   private int PX[] = new int[4];
   private int PY[] = new int[4];
   private int CTX[] = new int[52];
   private int CTY[] = new int[52];
   private int CBX[] = new int[52];
   private int CBY[] = new int[52];
   //private Color lightShadow = new Color(160, 160, 160);
   //private Color lightPuck   = new Color(200, 200, 200);
   private Color bgColor     = new Color(240,240,240);
   private Color lightShadow = new Color(128,128,128,128);
   private Color lightPuck   = new Color(255,255,255,128);
}

