package ps1;

import java.awt.*;
import java.awt.image.*;
import java.util.*;
import java.lang.*;


class Playfield extends Raster {  
  /** The Playfield class contains all the animatedssprites that are
   * drawn on the background raster. It also contains methods for
   * locating a sprite given any x,y coordinate from the raster that it
   * draws on. The Playfield is flexible in that any number of animated
   * sprites may be added to playfield after an instance has been
   * created.  
   *<P> 6.837 Problem set #1
   * @author Christina Chu
   */

  boolean b = false;
  Raster background;          // background image
  Vector spriteList;          // list of Animated sprites on this playfield
  int numsprites;             // since I don't know how many sprites I would add, I chose
  Component root;             // vectors, because they can expand to an infinite size.

  /** 
   * The Playfield constructor sets the Playfield background
   * images, and takes in an argument which is the number of sprites
   * that the Playfield will contain.  
   */

  public Playfield(Image bgnd, int numSprites) {
    Raster background = new Raster(bgnd);
    this.numsprites = numSprites;    
    spriteList = new Vector();    
  }

  ////////////////////////// Methods //////////////////////////
  /**
   * This method adds an Animated sprite object to
   * the end of the sprite vector
   * @param i, index of the sprite
   * @param s, animated sprite to be added
   */
  public void addSprite(int i, AnimatedSprite s) {    
    try {
      spriteList.addElement(s);
    } catch(ArrayIndexOutOfBoundsException e) {
      System.err.println("Adding Sprite to Playfield " + e);
    }
  }
  
  /**
   * This method copies over the original raster's
   * pixels and keeps them for refreshing the entire
   * background in a local pixel array
   * @param bgnd, the background raster
   */

  public void clearBackground(Raster bgnd) {
    for (int w=0; w< bgnd.arrlen(); w++) {
      bgnd.pixel[w] = background.pixel[w];
    }
  }

  /**
   * This method draws the playfield background
   * and the sprites on the playfield. The first time
   * it is called, it stores a copy of the original background
   * for refreshing. It then draws the background and the
   * animated sprites on the raster. It then waits, in order
   * to allow the rendering environment to update. 
   *
   * @param root, the component from applet
   * @param bgnd, the background raster
   */

  public void Draw(Component root, Raster bgnd) {           
    // copy initial background passed to playfield, save
    // for future reference.
    if (b == false) {
      background = new Raster(bgnd.Width(), bgnd.Height());
      for (int i =0; i< bgnd.arrlen(); i++) {
	background.pixel[i] =  bgnd.pixel[i];
      }
      b = true;  // do this only the first time.
    }
    /////////////////////////////////////////
    // redraw background    
    clearBackground(bgnd);
    Image output = null;

    // Do for all Animated Sprites in spriteList
    for (int i =0; i<spriteList.size(); i++) {
      AnimatedSprite s = (AnimatedSprite)spriteList.elementAt(i);
      if (s.frame <= s.total) {
	s.Draw(root,bgnd);
	output = bgnd.toImage(root);        
      }
      // System.out.println("s.frame, i, s.frames:  " +
      // s.frame + " " + i + " "  +s.frames ); 
    }       
    sleeper(10);
  }

  /**
   * This method spawns a thread that sleeps for t ms 
   * @param t
   *
   */


  public void sleeper(int t) {
    Thread th = new Thread();
    try { 
      th.sleep(t);      
    } catch(InterruptedException e) {
      // do something here? 
    }    
  }

  /**
   * This method switches the track of the animated
   * sprite. It also sets the sprite at location x,y
   *
   * @param index, number of track to switch to.
   * @param x, x coordinate for new track
   * @param y, y coordinate for new track
   *
   */


  public void switchTrack(int index, int x, int y) {
    // switch sprite track in response to mouse event.
    AnimatedSprite as = (AnimatedSprite)spriteList.elementAt(index);
    int track = as.track;
    if (track < (as.index-1)) {
      track++;
      as.setLocation(x,y);
      as.setTrack(track);
    } else {
      as.setTrack(track);
    }
  }

  /** This method finds the sprite at location x, y 
   * returns an Animated Sprite for that location 
   * else returns null
   * @param x
   * @param y 
   */

  public AnimatedSprite findSprite(int x, int y) {
    AnimatedSprite asp = null;
    for (int m=0; m< spriteList.size() ; m++) {
      AnimatedSprite as = (AnimatedSprite)spriteList.elementAt(m);
      // tests if for a given point there is a non transparent
      // pixel of the sprite.
      if (as.pointInSprite(x,y)){  	   
	asp = as;
	break;
      }
    }
    return asp;
  }

  /** This method tests if for a given point
   * there is a non transparent pixel of the sprite.
   * It returns the integer index of the AnimatedSprite
   * in the spriteList that contains the given point.
   * @param x
   * @param y 
   */

  public int findIndexOfSprite(int x, int y) {
    int r = -1;
    for (int m=0; m< spriteList.size() ; m++) {
      AnimatedSprite as = (AnimatedSprite)spriteList.elementAt(m);
      if (as.pointInSprite(x,y)){  	   
        r = m;
	break;
      }
    }
    return r;
  }
}




