import java.awt.*;
import java.util.*;
import Raster;

class AnimatedSprite extends Raster {
  private final static int ANIMATIONS = 4;
  Image image;			// The input image, keep it around for copying
  int x, y;			// sprite position
  int width, height;		// the width and height of a single animation frame
  int frames;			// the number of animation frames
  short track[][];		// a track keeps a sequence of states for each animation
  short length[];		// the length (number of states) in each track
  short curAnim;		// current animation
  short nextAnim;		// the track after the current one
  short curState;		// current state within the current animation
  short curTick;		// current tick (within a current state)

  /**
   * Constructor: images = set of animation frames concatenated into single image 
   * (horizontally), frames is the number of such frames in images.
   */
  public AnimatedSprite(Image images, int frames)
  {
    super(images);		// Call the Raster constructor to store the sprite images

    System.out.println("Created Raster.");

    /* initialize the class variables */
    this.image = images;
    this.frames = frames;	
    this.width = super.width / frames; 
    this.height = super.height; 
    track = new short[ANIMATIONS][]; 
    length = new short[ANIMATIONS];	
    x = y = 0;
    curAnim = 0;
    nextAnim = 0;
    curState = 0;
    curTick = 0;
  }

  public AnimatedSprite(AnimatedSprite s) // produce a copy of this Sprite
 {
    super(s.image);		// Call the Raster constructor
    /* initialize the class variables */
    this.image = s.image;
    this.frames = s.frames;	
    this.width = s.width;
    this.height = s.height;
    track = s.track;		// Shared structure
    length = s.length;		// Shared structure
    x = s.x; 
    y = s.y;
    curAnim = 0;		// Reset state
    nextAnim = 0;
    curState = 0;
    curTick = 0;
  }

  public void addTrack(int anim, StringTokenizer parse)
  {
    int nframes, frame, dx, dy, ticks;

    try {
      while (parse.hasMoreTokens()) {
	frame = Integer.parseInt(parse.nextToken());
	ticks = Integer.parseInt(parse.nextToken());
	dx = Integer.parseInt(parse.nextToken());
	dy = Integer.parseInt(parse.nextToken());
	addState(anim,frame,ticks,dx,dy);
      }
    } catch (NumberFormatException e) {
    }
  }

  /**
   * A track is a series of states. A state specifies that a frame is
   * displayed for ticks periods. The sprite's position is then moved
   * (dx, dy) pixels.  This method adds a state to track t.
   */
  public void addState(int t, int frame, int ticks, int dx, int dy)
  {

    if (t >= 0 && t < ANIMATIONS) { // check for legal track
      if (track[t] == null) {	// previously uninitialized track
	track[t] = new short[4*16];
	length[t] = 0;
      }
      int tlen = length[t];
      if (tlen == track[t].length) {    // grow array as needed
	int n = 2*tlen;
	short tmp[] = new short[n];
	System.arraycopy(track[t], 0, tmp, 0, tlen);
	track[t] = tmp;
      }
      tlen *= 4;		// each state is four entries long
      track[t][tlen+0] = (short) frame;       // which frame to display
      track[t][tlen+1] = (short) ticks;       // for how many ticks
      track[t][tlen+2] = (short) dx;          // how far to move the sprite in x
      track[t][tlen+3] = (short) dy;          // how far to move the sprite in y
      length[t] += 1;
    }
  }

  /**
   * Actually draw the sprite into the bgnd Raster 
   */
  public void Draw(Raster bgnd)
  {
    // You need to provide this code
  }

  /**
   * Move to the next state along the current track.  If we reach the
   * end of the track, move to the next track (which may be the
   * current one).
   */
  public void nextState()
  {
    // You need to provide this code
  }

  public void setTrack(int t)
  {
    if (t >= 0 && t < ANIMATIONS)
      nextAnim = (short)t;	// set the track
  }

  public boolean notInView(Raster bgnd)
  {
    // You need to provide this code
  }

  public boolean overlaps(AnimatedSprite s)
  {
    // You need to provide this code
    // Just touching borders doesn't count as overlap.
  }
}
