// FlyingSaucer Class
// FlyingSaucer.java

// Imports
import java.awt.*;
import java.applet.Applet;

public class AnimatedFlyingSaucer extends Applet implements Runnable {
  private Image         offImage, back;//, saucer;
  protected static Image[] saucer = new Image[2];
  private Dimension     saucerSize;
  private Graphics      offGrfx;
  private Thread        animate;
  private MediaTracker  tracker;
  private SpriteVector  sv;
  protected ToggleSprite    theSaucer;
  protected int           lastKey;
  private int           delay = 83; // 12 fps

  public String getAppletInfo() {
    return (new String("Flying Saucer by Michael Morrison"));
  }

  public void init() {
    // Load and track the images
    tracker = new MediaTracker(this);
    back = getImage(getCodeBase(), "Res/Back.gif");
    tracker.addImage(back, 0);
    saucer[0] = getImage(getCodeBase(), "Res/Saucer1.gif");
    tracker.addImage(saucer[0], 0);
    saucer[1] = getImage(getCodeBase(), "Res/Saucer2.gif");
    tracker.addImage(saucer[1], 0);
  }

  public void start() {
    if (animate == null) {
      animate = new Thread(this);
      animate.start();
    }
  }

  public void stop() {
    if (animate != null) {
      animate.stop();
      animate = null;
    }
  }

  public void run() {
    try {
      tracker.waitForID(0);
    }
    catch (InterruptedException e) {
      return;
    }

    // Create and add the saucer
    sv = new SpriteVector(new ImageBackground(this, back));
    saucerSize = new Dimension(saucer[0].getWidth(this),
      saucer[0].getHeight(this));
//    theSaucer = new Sprite(this, saucer, new Point((size().width -
//      saucerSize.width) / 2, (size().height - saucerSize.height) /
//      2), new Point(0, 0), 0, Sprite.BA_STOP);
    theSaucer = new ToggleSprite(this, saucer, 0, 1, 20, new Point((size().width -
      saucerSize.width) / 2, (size().height - saucerSize.height) /
      2), new Point(0, 0), 0, Sprite.BA_STOP);
    sv.add(theSaucer);

    // Update everything
    long t = System.currentTimeMillis();
    while (Thread.currentThread() == animate) {
      sv.update();
      repaint();
      try {
        t += delay;
        Thread.sleep(Math.max(0, t - System.currentTimeMillis()));
      }
      catch (InterruptedException e) {
        break;
      }
    }
  }

  public void update(Graphics g) {
    // Create the offscreen graphics context
    if (offGrfx == null) {
      offImage = createImage(size().width, size().height);
      offGrfx = offImage.getGraphics();
    }

    // Draw the sprites
    sv.draw(offGrfx);

    // Draw the image onto the screen
    g.drawImage(offImage, 0, 0, null);
  }

  public void paint(Graphics g) {
    if ((tracker.statusID(0, true) & MediaTracker.ERRORED) != 0) {
      // Draw the error rectangle
      g.setColor(Color.red);
      g.fillRect(0, 0, size().width, size().height);
      return;
    }
    if ((tracker.statusID(0, true) & MediaTracker.COMPLETE) != 0) {
      // Draw the offscreen image
      g.drawImage(offImage, 0, 0, null);
    }
    else {
      // Draw the title message (while the images load)
      Font        f1 = new Font("TimesRoman", Font.BOLD, 28),
                  f2 = new Font("Helvetica", Font.PLAIN, 16);
      FontMetrics fm1 = g.getFontMetrics(f1),
                  fm2 = g.getFontMetrics(f2);
      String      s1 = new String("Flying Saucer"),
                  s2 = new String("Loading images...");
      g.setFont(f1);
      g.drawString(s1, (size().width - fm1.stringWidth(s1)) / 2,
        ((size().height - fm1.getHeight()) / 2) + fm1.getAscent());
      g.setFont(f2);
      g.drawString(s2, (size().width - fm2.stringWidth(s2)) / 2,
        size().height - fm2.getHeight() - fm2.getAscent());
    }
  }

  public boolean keyDown(Event evt, int key) {
    // Change the saucer velocity based on the key pressed
    Point vel = theSaucer.getVelocity();
    switch (key) {
    case Event.LEFT:
      vel.x = -4;
      if (lastKey == Event.LEFT)
        vel.y = 0;
      break;
    case Event.RIGHT:
      vel.x = 4;
      if (lastKey == Event.RIGHT)
        vel.y = 0;
      break;
    case Event.UP:
      vel.y = -4;
      if (lastKey == Event.UP)
        vel.x = 0;
      break;
    case Event.DOWN:
      vel.y = 4;
      if (lastKey == Event.DOWN)
        vel.x = 0;
      break;
    default:
      vel.x = vel.y = 0;
    }
    theSaucer.setVelocity(vel);
    lastKey = key;
    return true;
  }

  public boolean mouseDown(Event evt, int x, int y) {
    theSaucer.setPosition(new Point(x - (saucerSize.width / 2),
      y - (saucerSize.height / 2)));
    return true;
  }

  public boolean mouseDrag(Event evt, int x, int y) {
    theSaucer.setPosition(new Point(x - (saucerSize.width / 2),
      y - (saucerSize.height / 2)));
    return true;
  }
}
