import java.applet.*;
import java.awt.*;
import java.io.*;
import java.net.*;
import Drawable;
import Raster;
import Sphere;

public class SphereTest2 extends Applet {
    final static int CHUNKSIZE = 100;
    Raster raster;
    Image screen;
    Sphere splatList[];
    int splats;
    int reps;
    int cx, cy;

    public void init( ) {
      raster = new Raster(size().width, size().height);
      raster.fill(getBackground());
      screen = raster.toImage( );
      cx = size().width / 2;
      cy = size().height / 2;

      splatList = new Sphere[CHUNKSIZE];
      splats = 0;

      System.out.println("Getting data field parameter " );
      String filename = getParameter("datafile");
      showStatus("Reading " + filename);
      System.out.println("Reading " + filename);
      InputStream is = null;
      try {
        is = new URL(getDocumentBase(), filename).openStream();
        ReadInput(is);
        is.close();
      } catch (IOException e) {
        showStatus("Error reading "+filename);
      }
      showStatus("Splats = " + splats);
      System.out.println("Splats = " + splats);

      reps = 1;
      String rString = getParameter("repetitions");
      if (rString != null) {
        reps = Integer.decode(rString).intValue();
      }
      DrawScene(cx, cy);
    }

    private double getNumber(StreamTokenizer st) throws IOException {
      if (st.nextToken() != StreamTokenizer.TT_NUMBER) {
        throw new IOException(st.toString());
      }
      return st.nval;
    }

    public void ReadInput(InputStream is) throws IOException {
      float x, y, r;
      int rgb;

        StreamTokenizer st = new StreamTokenizer(is);
        st.eolIsSignificant(true);
        st.commentChar('#');

      scan:
      while (true) {
        switch (st.nextToken()) {
            default:
                break scan;
          case StreamTokenizer.TT_EOL:
                break;
          case StreamTokenizer.TT_WORD:
                if (st.sval.equals("d")) {
                  x = (float) getNumber(st);
                  y = (float) getNumber(st);
                  r = (float) getNumber(st);
              rgb = (255 << 8) | (int) getNumber(st);
              rgb = (rgb << 8) | (int) getNumber(st);
              rgb = (rgb << 8) | (int) getNumber(st);
              if (splats >= splatList.length) {
                Sphere newList[] = new Sphere[splatList.length + CHUNKSIZE];
                System.arraycopy(splatList, 0, newList, 0, splatList.length);
                splatList = newList;
              }
              splatList[splats] = new Sphere(x, y, r, rgb);
              splats += 1;
                }
        }
        if (splats % 100 == 0) showStatus("splats = " + splats);
        }

      is.close();
        if (st.ttype != StreamTokenizer.TT_EOF)
          throw new IOException(st.toString());
      }

    public void paint(Graphics g) {
      g.drawImage(screen, 0, 0, this);
    }

    public void update(Graphics g) {
      paint(g);
    }

    public boolean mouseDown(Event e, int x, int y) {
      Sphere new_list[] = new Sphere[splatList.length+1];

      for (int l=0; l<splatList.length; l++ ) {
              new_list[l] = splatList[l];
      }
      
      new_list[new_list.length-1] = new Sphere( (int) (100 + 200*Math.random()),
                                                  (int) (100 + 200*Math.random()),
                                                (int) (60*Math.random()),
                                                ((int) ( Integer.MAX_VALUE*
                                                         Math.random() )) |
                                                         0xff000000 ); 
      splatList = new_list;
      
      System.out.println( "Added random blob" );
      
          DrawScene(x, y);

      return true;
    }

    public boolean mouseDrag(Event e, int x, int y) {
      if (!e.metaDown()) {
          DrawScene(x, y);
      }
      return true;
    }

    protected void DrawScene(int x, int y) {
      float lx = x - cx;
      float ly = y - cy;
      float lz = (float) (cx*cx - lx*lx - ly*ly) / cx;
      Sphere.setLightDir(lx, ly, lz);
      if ( splatList == null ) return;
      for (int i = 0; i < splatList.length; i++) {
          if ( splatList[i] != null )
        splatList[i].Draw2(raster);
    }
      screen = raster.toImage( );
      repaint( );
    }
}