import java.applet.*;
import java.awt.*;
import java.net.*;

class Animate extends Thread
{
  Marcus mskay;

  public Animate(Marcus who)
  {
    mskay = who;
  }

  public void run()
  {
    while(mskay.running)
    {
	mskay.advanceFrame();
  	mskay.repaint();
	try
	{
	  sleep(mskay.sleeptime);
	}
	catch(Exception e){}
    }
  }
}

public class Marcus extends Applet
{
  int nframe;
  Image image[];
  AudioClip audio[];
  URL url[];
  int sleeptime;
  MediaTracker tracker;
  Animate animate;
  int frame;
  boolean running;

  private Image offScreenImage;
  private Dimension offScreenSize;
  private Graphics offScreenGraphics;

  public void advanceFrame()
  {
	frame = (frame + 1) % nframe;
  }

  public void init()
  {
	String parameter;

	// init number of frames
	parameter = getParameter("nframe");
	if (parameter == null)
	  System.out.println("Error: invalid parameter: nframe");
	else
	  nframe = Integer.parseInt(parameter);

	// init images
	image = new Image[nframe];
	tracker = new MediaTracker(this);
	for (int i = 0; i < nframe; i++)
	{
	  parameter = getParameter("image"+i);
	  if (parameter == null)
	    System.out.println("Error: invalid parameter: image"+i);
	  else
	  {
	    image[i] = getImage(getDocumentBase(), parameter);
	    tracker.addImage(image[i], i);
	  }
	}
	try
	{
	  tracker.waitForAll();
	}
	catch (InterruptedException e)
	{
	  System.out.println("Error waiting for image to load.");
	}

	// init audio
	audio = new AudioClip[nframe];
	for (int i = 0; i <nframe; i++)
	{
	  parameter = getParameter("audio"+i);
	  if (parameter != null)
	    audio[i] = getAudioClip(getDocumentBase(), parameter);
	}

	// init url
	url = new URL[nframe];
	for (int i = 0; i <nframe; i++)
	{
	  parameter = getParameter("url"+i);
	  if (parameter != null)
	  {
	  	try
	  	{
	    	  url[i] = new URL(parameter);
	 	}
	  	catch(MalformedURLException mal)
	  	{
	    	 System.out.println("Error locating URL address.");
	  	}
	  }
	}

	// init sleep time
	parameter = getParameter("sleeptime");
	if (parameter == null)
	  sleeptime = 1000;
	else
	  sleeptime = Integer.parseInt(parameter);	  
  }

  public void paint (Graphics g)
  {
    g.drawImage(image[frame], 0, 0, null);    
  }

  public final synchronized void update (Graphics g)
  {
    Dimension d = size();
    if((offScreenImage == null) || (d.width != offScreenSize.width) ||  (d.height != offScreenSize.height))
    {
      offScreenImage = createImage(d.width, d.height);
      offScreenSize = d;
      offScreenGraphics = offScreenImage.getGraphics();
    }
    offScreenGraphics.setColor(getBackground());
    offScreenGraphics.fillRect(0, 0, d.width, d.height);
    paint(offScreenGraphics);
    g.drawImage(offScreenImage, 0, 0, null);
  }


  public void stop()
  {
	running = false;
	destroy();
  }

  public boolean mouseDown(Event evt, int x, int y)
  {
	if (audio[frame] != null)
          audio[frame].play();
	return true;
  }
  public boolean mouseUp(Event evt, int x, int y)
  {
	if (url[frame] != null)
	  getAppletContext().showDocument(url[frame]);
	return true;
  }

  public boolean mouseEnter(Event evt, int x, int y)
  {
	running = true;
        animate = new Animate(this);
        animate.start();
	return true;
  }

  public boolean mouseExit(Event evt, int x, int y)
  {
	running = false;
	return true;
  }
}
