// John Kalstrom
// Java Fundamentals I animation assignment, 10/97
// "Gratuitous Spinning Corporate Logo"

import java.awt.Graphics;
import java.awt.Image;
import java.awt.Color;
import java.util.Random;
import java.awt.Event;

public class Logo extends java.applet.Applet 
                  implements Runnable {
  Graphics offscreenGraphics;
  Image offscreenImage;
  Image logo_pics[];
  int logo_MAX;
  int logo_idx = 0, spin_dir = 1, spin_delay = 100;
  Thread runner;
  int xpos = 0, xspd = 5;
  int ypos = 0, yspd = 5;
  int XMAX, YMAX, logo_XMAX, logo_YMAX;
  static int logo_SPEED = 30, BUMPER_SIZE = 5;
  Random rnd = new Random();

  public void init() {
    logo_pics = new Image[11];
    // DecimalFormat fmt = new DecimalFormat("00");   // security violation!

    // Create offscreen image to draw in.  (For double-buffering)
    // And a graphics object to get at methods to draw on it with
    XMAX = size().width - 1;
    YMAX = size().height - 1;
    offscreenImage = createImage(XMAX, YMAX);
    offscreenGraphics = offscreenImage.getGraphics();

    // 'File("images").list()' generates security violation!
    logo_MAX = logo_pics.length-1;
    for (int idx=1; idx <= logo_MAX+1; ++idx) {
      if (idx < 10)
        logo_pics[idx-1] = getImage(getCodeBase(), "images/logo0"+ idx + ".gif");
      else
        logo_pics[idx-1] = getImage(getCodeBase(), "images/logo"+ idx + ".gif");

      // Actually go get the image, so we can get its size
      prepareImage(logo_pics[idx-1], this);
    }

    // Wait until image has been loaded, then set bounce size
    while ((checkImage(logo_pics[logo_MAX], this) & (WIDTH | HEIGHT)) != (WIDTH | HEIGHT)) ;
    logo_XMAX = XMAX - logo_pics[logo_MAX].getWidth(this) - BUMPER_SIZE;
    logo_YMAX = YMAX - logo_pics[logo_MAX].getHeight(this) - BUMPER_SIZE;
  }
    
  public void start() {
    if (runner == null) {
      runner = new Thread(this);
      runner.start();
    }
  }

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

  public void run() {
    // Runner thread -- does animation
    for (logo_idx = 0; Thread.currentThread() == runner;
         logo_idx += spin_dir)
    {
      // Draw
      if (logo_idx < 0)
         logo_idx = logo_MAX;
      if (logo_idx > logo_MAX)
         logo_idx = 0;
      offscreenGraphics.setColor(new Color(0xA0, 0x80, 0xFF));
      offscreenGraphics.fillRect(0, 0, XMAX, YMAX);         // Rubber bumpers
      offscreenGraphics.setColor(Color.black);
      offscreenGraphics.fillRect(5, 5, XMAX-10, YMAX-10);   // Black background
      offscreenGraphics.drawImage(logo_pics[logo_idx], xpos, ypos, this);   // Logo
	repaint();
      pause(spin_delay);

      // Move
      xpos += xspd;
      if (xpos < BUMPER_SIZE || xpos > logo_XMAX)
      {
         xspd = -xspd + (int)(5 * (rnd.nextFloat() - 0.5));
         xspd = Math.min(xspd, logo_SPEED);
         xspd = Math.max(xspd, -logo_SPEED);
         xpos = Math.min(xpos, logo_XMAX);
         xpos = Math.max(xpos, BUMPER_SIZE);
      }
      ypos += yspd;
      if (ypos < BUMPER_SIZE || ypos > logo_YMAX)
      {
         yspd = -yspd + (int)(5 * (rnd.nextFloat() - 0.5));
         yspd = Math.min(yspd, logo_SPEED);
         yspd = Math.max(yspd, -logo_SPEED);
         ypos = Math.min(ypos, logo_YMAX);
         ypos = Math.max(ypos, BUMPER_SIZE);
      }
    }
  }
  
  public boolean mouseDown(Event evt, int x, int y) {
    // Right click -- change direction and speed of spin
    if (evt.metaDown())
    {
      spin_dir = -spin_dir;
      spin_delay = 50 + (int)(rnd.nextFloat() * 100);
    }
    else
    {
      // Left click -- set location of logo
      xpos = x - (logo_pics[0].getWidth(this) / 2);
      ypos = y - (logo_pics[0].getHeight(this) / 2);
    }
    return true;
  }

  void pause(int time) {
    try { Thread.sleep(time); }
    catch (InterruptedException e) { }
  }

  // Override, to avoid clearing with white
  public void update (Graphics g) {
      paint(g);
  }

  public void paint(Graphics g) {
    g.drawImage(offscreenImage, 0, 0, this);
  }

  public void destroy() {
    offscreenGraphics.dispose();
  }
}