package ps1;

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

/**
 * This class reads PARAM tags from its HTML host page and sets
 * the color and label properties of the applet. Program execution
 * begins with the init() method. 
 */
public class Project1 extends Applet implements Runnable, MouseListener
{
  // Declarations
  private Playfield pfield;
  private Thread mainThread;
  private Image iOutput;
  Image bat[] = new Image[10];
  MediaTracker m;
  Image bg;
  Sprite sp;
  
  /**
   * The entry point for the applet. 
   */
  public void init()
  {
    // Declarations
    int a;
    pfield = new Playfield(300, 300);
    m = new MediaTracker(this);

    // Initialize the applet's form.
    this.setBackground(Color.lightGray);
    this.setForeground(Color.black);
    this.setLayout(new BorderLayout());

    // use the parameters added to the page.
    usePageParams();
    
    // Need to add the sprites, initialize the playfield, and set up the game.
    
    // need to get the background image
    // bg = getImage(getDocumentBase(), "images/bg1.gif");
    // m.addImage(bg, 0);

    // Get the bat images
    for(a=0;a<10;a++)
      {
	bat[a] = getImage(getDocumentBase(), "images/bat"+a+".gif");
	m.addImage(bat[a], 1);
      }
  }    

  /** 
   * This starts the applet up.
   */
  public void start()
  {
    mainThread = new Thread(this);
    mainThread.start();
  }

  /**
   * This stops the applet.
   */
  public void stop()
  {
    mainThread.stop();
    mainThread = null; 
  }

  public void run()
  {
    try
      {
	//m.waitForID(0);
	m.waitForID(1);
      }
    catch(InterruptedException e)
      {
	return;
      }
    
    if(sp == null)
      {
	sp = CreateBat();
	renderPlayfield();
      }

    while(true)
      {
	try
	  {
	    mainThread.sleep(50);
	  }catch (InterruptedException e){}
	  renderPlayfield();
	  repaint();
      }
  }

  /**
   * This function paints the playfield.
   */
  public void paint(Graphics g)
  {
    if((m.statusAll(false) & MediaTracker.ERRORED) != 0)
      {
	g.setColor(Color.red);
	g.fillRect(0, 0, getSize().width, getSize().height);
      }
    else if((m.statusID(0, true) & MediaTracker.LOADING) != 0)
      {
	g.setColor(Color.white);
	g.fillRect(0,0, getSize().width, getSize().height);
      }
    else if(((m.statusID(1, true) & MediaTracker.LOADING) != 0) && 
	    ((m.statusID(1, true) & MediaTracker.ERRORED) != 0))
      {
	//g.drawImage(bg, 0, 0, this);
      }
    else
      {
	if(iOutput != null) 
	  g.drawImage(iOutput, 0, 0, this);
      }
  }
  
  /**
   * This function updates the screen
   */
  public void update(Graphics g)
  {
    paint(g);
  }

  /**
   * This does the rendering under the hood.
   */
  public void renderPlayfield()
  {
    pfield.updateSprites(getSize().width, getSize().height);
    iOutput = pfield.updateImage();
  }
  
  // This creates a bat sprite
  public Sprite CreateBat()
  {
    // Declarations
    int a = 0, b = 0;
    Sprite newB;

    newB = new Sprite(10, "bat1");
    
    // Add the bat images
    for(a=0;a<10;a++)
      newB.AddImage(bat[a]);

    // Create the transitions
    // These transitions apply regardless of the change in x or y
    for(a=0;a<10;a++)
      {
	if(a == 9)
	  b = 0;
	else
	  b = a + 1;
	
	newB.AddTransition(true, 0, 0, a, b);
      }
    
    // initialize the sprite in the center of the screen.
    // need to implement z-order checking to deal with creation over a spot 
    // that already has a sprite.
    try
      {
	newB.initSprite(40, 40, 0, 0);
      }
    catch(UninitializedException e)
      {}
    
    pfield.addSprite(newB);
    
    return(newB);
  }

  // Event stubs
  public void mouseClicked(MouseEvent e)
  {
    Sprite l;
    
    l = pfield.InSprite(e.getX(), e.getY());
    
    if(l != null)
      sp = l;
  }
  
  public void mousePressed(MouseEvent e)
  {
  }

  public void mouseReleased(MouseEvent e)
  {
  }

  public void mouseExited(MouseEvent e)
  {
  }

  public void mouseEntered(MouseEvent e)
  {
  }

/**
   * Reads parameters from the applet's HTML host and sets applet
   * properties.
   */
  private void usePageParams()
  {
    final String defaultLabel = "Default label";
    final String defaultBackground = "C0C0C0";
    final String defaultForeground = "000000";
    String labelValue;
    String backgroundValue;
    String foregroundValue;

    /** 
     * Read the <PARAM NAME="label" VALUE="some string">,
     * <PARAM NAME="background" VALUE="rrggbb">,
     * and <PARAM NAME="foreground" VALUE="rrggbb"> tags from
     * the applet's HTML host.
     */
    labelValue = getParameter("label");
    backgroundValue = getParameter("background");
    foregroundValue = getParameter("foreground");

    if ((labelValue == null) || (backgroundValue == null) ||
	(foregroundValue == null))
      {
	/**
	 * There was something wrong with the HTML host tags.
	 * Generate default values.
	 */
	labelValue = defaultLabel;
	backgroundValue = defaultBackground;
	foregroundValue = defaultForeground;
      }

    /**
     * Set the applet's string label, background color, and
     * foreground colors.
     */
    //label1.setText(labelValue);
    //label1.setBackground(stringToColor(backgroundValue));
    //label1.setForeground(stringToColor(foregroundValue));
    this.setBackground(stringToColor(backgroundValue));
    this.setForeground(stringToColor(foregroundValue));
  }

  /**
   * Converts a string formatted as "rrggbb" to an awt.Color object
   */
  private Color stringToColor(String paramValue)
  {
    int red;
    int green;
    int blue;
    
    red = (Integer.decode("0x" + paramValue.substring(0,2))).intValue();
    green = (Integer.decode("0x" + paramValue.substring(2,4))).intValue();
    blue = (Integer.decode("0x" + paramValue.substring(4,6))).intValue();
    
    return new Color(red,green,blue);
  }

}
