import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;
import AnimatedSprite;
import Playfield;

public class Invaders extends Applet implements Runnable {
  // Game parameters
  private final static int NROWS = 4, NCOLS = 6;
  private final static String[] paramNames = {"defender", "invader", "missile", "bomb"};
  private final static int defenderId = 0, invaderId = 1, missileId = 2, bombId = 3;

  Playfield playfield;
  Image output;
  Thread animate;
  Vector invaders, missiles, bombs;
  AnimatedSprite defender;
  AnimatedSprite baseSprites[];
  boolean gameOn;
  int tick, bgWidth, bgHeight;
  int bgScrollX, bgScrollY;		// background scroll
    
  public void init()
  {
    String tokens, filename;
    StringTokenizer parse;
    int nframes;
    AnimatedSprite sprite;

    gameOn = false;
    tick = 0;			// global time counter

    playfield = new Playfield(getImage(getDocumentBase(), getParameter("background")));
    bgWidth = playfield.getWidth();
    bgHeight = playfield.getHeight();
    bgScrollX = Integer.parseInt(getParameter("backgroundScrollX"));
    bgScrollY = Integer.parseInt(getParameter("backgroundScrollY"));

    baseSprites = new AnimatedSprite[4];

    // Read in the animation tracks for each type of sprite
    for (int i = 0; i < 4; i++) {
      tokens = getParameter(paramNames[i]);
      if (tokens != null) {
	parse = new StringTokenizer(tokens, ", ");
	filename = parse.nextToken();
	nframes = Integer.parseInt(parse.nextToken());
	baseSprites[i] = new AnimatedSprite(getImage(getDocumentBase(), filename), nframes);
	// Fill in animation...
	// ...
      }
      else 
	baseSprites[i] = null;
    }

    // Do additional initialization
    // ...

    addMouseListener(new MouseKeeper());	// Listen for button events
  }

  public void start() 
  {
    animate = new Thread(this);
    animate.start();
  }

  public void stop() 
  {
    animate = null;
  }

  public void run() 
  {
    while (true) {
      try {
	animate.sleep(100);
      } catch (InterruptedException e) {
      }
      renderPlayfield( );
    }
  }

  public synchronized void startGame( )
  {
    // Initialize sprites etc
    // ...
  }


  public synchronized void renderPlayfield( ) 
  {
    // Do whatever is needed to construct the image for the playfield
    // ...

    // Draw the picture
    playfield.Draw();
    output = playfield.toImage(this);

    // Scroll
    playfield.scroll(bgScrollX, bgScrollY);
    // Any additional actions to advance the state of the game
    // ...

    // Call for painting
    repaint();
  }

  public void paint(Graphics g) 
  {
    if (output != null)
      g.drawImage(output, 0, 0, this);
    if (gameOn)
      showStatus("Tick:"+tick+
		 " Invaders:"+invaders.size()+
		 " Missiles:"+missiles.size()+
		 " Bombs:"+bombs.size());
    
    else
      g.drawString("CLICK TO BEGIN", bgWidth/2, bgHeight/2);
  }

  public void update(Graphics g) 
  {
    paint(g);
  }

  private class MouseKeeper extends MouseAdapter 
  {
    // During the game, move the defender and fire a missile
    // Otherwise, start the game
    public void mousePressed (MouseEvent e) 
    {
      // You need to provide this code
      if (gameOn) {
	//...
      }
      else 
	startGame();
    }
  }

}
