//
// Perhaps:  try making a raster have a graphics object as well!

import java.awt.*;
import java.awt.event.*;
import java.applet.*;

public class Ps1 extends Applet implements Runnable { 

  /*
   * Constants
   */ 
  private static final long GC_INTERVAL    = 10000;  // Millis between each System.gc()
  private static final int  framerate      = 8;      // Desired FPS
  private static final long millisPerFrame = 1000 / framerate;   

  /*
   * Member variables
   */
  private Thread    m_animator;
  private Image     m_imgBuffer;
  private int       m_lastGC;
  private Playfield m_pf;

  
  /*
   * Initializes the Applet, and draws the first frame of the
   * animation.
   */
  public void init()
  {
    // Create a new playfield of 1200x300 pixels,
    // to be viewed on a 400x300 display.
    m_pf = new Playfield(1200, 300, 400, 300);

    //
    // Add the background to the playfield
    Layer background = new Layer(getImage(getDocumentBase(), 
					  "./wilan/WilanBg.gif"));
    m_pf.addLayer(background);

    //
    // Add Wilan (the main character) to the playfield
    Wilan wilan = new Wilan(getImage(getDocumentBase(), 
				     "./wilan/WilanComplete.gif"));
    wilan.setControllable(true);  // Wilan can be controlled by the user 
    wilan.setFocus(true);         // Wilan not affected by scrolling playfield
    wilan.setX(90);               // Set Wilan's starting position
    wilan.setY(200);
    m_pf.addSprite(wilan);        // Add Wilan to the playfield
    
    //
    // Add the mean ol' dragon in a hidden location off-screen
    Dragon dragon = new Dragon(getImage(getDocumentBase(), 
					"./wilan/DragonStrip.gif"));
    dragon.setControllable(false); // Dragon cant be controlled by the user
    dragon.setFocus(false);        // Dragon is affected by scrolling playfield
    dragon.setX(1100);             // Set Dragon's starting position
    dragon.setY(0);
    m_pf.addSprite(dragon);        // Add Dragon to the playfield

    // Set up Sprite's KeyListeners
    m_pf.setEventSource(this);    
    m_pf.setParent(this);

    // Draw the display
    m_pf.draw(); 
  }

  /*
   * Starts the execution of the Applet by creating a Thread
   * to continually repaint the display
   */
  public void start()
  {        
    m_animator = new Thread(this);
    m_animator.start();
  }


  /**
   * This method is called by the thread that was created in
   * the start method. It does the main animation.
   */
  public void run() {

    long m_lastGC = System.currentTimeMillis();
    long tm;

    while (Thread.currentThread() == m_animator) {
      
      tm = System.currentTimeMillis();
      
      //
      // Force the system to garbage collector regularly
      if (tm > (m_lastGC + GC_INTERVAL)) 
	{
	  System.gc();
	  m_lastGC = tm;
	}
	
      m_pf.draw();
      //System.out.println("Time to draw: " + (System.currentTimeMillis() - tm));
      m_imgBuffer = m_pf.getDisplay().toImage();

      repaint();
      
      try {
	tm += millisPerFrame;
	Thread.sleep(Math.max(0, tm - System.currentTimeMillis()));
      } catch (InterruptedException e) {
	break;
      }
      
    }
  }

  /*
   * Stops the execution of this Applet
   */
  public void stop()
  {
    getGraphics().drawString("Nice job.  You killed Wilan.", 100, 250);
    m_animator.stop();
  }

  /*
   * Repaints the Applet
   */
  public void paint(Graphics g)
  {
    update(g);
  }
  
  /*
   * Draws our offscreen buffer to the Applet's 
   * Graphics context
   */
  public void update(Graphics g)
  {
    g.drawImage(m_imgBuffer, 0, 0, this);
  }
}






