// Travis Furrer
// 6.837 Project 1
// September 28, 1998

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

/**
 * A PlayField is a raster that scrolls and tiles itself onto another
 * raster, which is to be drawn directly.  A PlayField has associated
 * with it any number of sprites, and they can be moved around using
 * the mouse.
 * */
public class PlayField extends Raster implements MouseListener {
    //The raster on which everything (background and sprites) is to be drawn.
    public Raster raster = null;

    //Number of milliseconds to pause between drawing each frame (NOT
    //the framerate, since frames take a nonzero amount of time to
    //draw).
    public int frameTime = 500;

    //A list of sprites on this playfield.
    public Vector sprites = new Vector(3);

    //This variable keeps track of which sprite the user is moving
    //with the mouse.
    public int curSprite = 0;

    //Used to cause the applet to repaint when frames are updated.
    public Panel parentPanel = null;

    //The thread that runs to continue the animation of this applet.
    Thread animThread;


    public PlayField(Image img, int frameTime, Raster raster, Panel p) {
	super(img);
	this.frameTime = frameTime;
	this.raster = raster;
	parentPanel = p;
    }


    //Add a sprite to this playfield.
    public void addSprite(Sprite s) {
	sprites.addElement(s);
    }


    public void mouseClicked(MouseEvent e) {
    }


    //Allow the user to move sprites around, or to query pixels about
    //whether a sprite is there.
    public void mousePressed(MouseEvent e) {
	int i,x,y, sprite = -1;
	Sprite s;
	x = e.getX();
	y = e.getY();
	if ((e.getModifiers() & InputEvent.BUTTON2_MASK) ==
	    InputEvent.BUTTON2_MASK) {
	    //Button 2 pressed.  Report which (if any) sprites are here.
	    System.out.println("Point "+x+","+y);
	    for (i = 0; i<sprites.size(); i++) {
		s = (Sprite)sprites.elementAt(i);
		if (s.includesPixel(x,y)) {
		    System.out.println("  Inside "+s.name);
		} 
	    }
	    System.out.println();
	} else {
	    //Button 1 pressed.  Move or set current sprite.
	    for (i = 0; i<sprites.size(); i++) {
		s = (Sprite)sprites.elementAt(i);
		if (s.includesPixel(x,y)) {
		    sprite = i;
		} 
	    }
	    if (sprite > -1) {
		//Set current sprite to LAST of the sprites that we are in.
		curSprite = sprite;
	    } else {
		//Send current sprite to this destination.
		s = (Sprite)sprites.elementAt(curSprite);
		s.destination = new Point(x-(s.width/2),y-(s.height/2));
	    }
	}
    }

    
    public void mouseReleased(MouseEvent e) {
    }


    public void mouseEntered(MouseEvent e) {
    }


    public void mouseExited(MouseEvent e) {
    }


    //Start a thread to handle the animation and moving of sprites.
    public void start() {
	animThread = new Thread() {
	    public void run() {
		int animpos = 0,s,i,j;
		while (animThread == this) {
		    //Wait for time to draw next frame.
		    try {
			Thread.sleep(frameTime);
		    } catch (InterruptedException e) {}		    
		    if (animpos > 0) {
			animpos -= 1;
		    } else {
			animpos = width;
		    }

		    //Draw scrolling background.
		    for (i=0; i<raster.width; i++) {
			for (j=0; j<raster.height; j++) {
			    raster.setPixel(
					    getPixel((animpos+i)%width,
							       j%height),
					    i,
					    j);
			}
		    }

		    //Draw sprites, with correct clipping.
		    Sprite sprite;
		    int pix;
		    int x1,y1,x2,y2;
		    for (s=0; s<sprites.size(); s++) {
			//Get a sprite.
			sprite = (Sprite)(sprites.elementAt(s));
			sprite.nextFrame();
			sprite.updateFrame();

			//Find region inside raster.
			x1 = 0;
			y1 = 0;
			x2 = sprite.width-1;
			y2 = sprite.height-1;
			if (sprite.location.x < 0) {
			    x1 = -sprite.location.x;
			}
			if (sprite.location.y < 0) {
			    y1 = -sprite.location.y;
			}
			if (sprite.location.x + sprite.width > raster.width) {
			    x2 = raster.width - sprite.location.x;
			}
			if (sprite.location.y+sprite.height > raster.height) {
			    y2 = raster.height - sprite.location.y;
			}

			//Copy the region onto the raster.
			for (i=x1; i<x2; i++) {
			    for (j=y1; j<y2; j++) {
				pix = sprite.getPixel(i,j);
				if (pix < 8388607) 
				{
				    raster.setPixel(pix,
						    i+sprite.location.x,
						    j+sprite.location.y);
				}
			    }
			}
		    }

		    //Paint the new frame (playfield + sprites).
		    parentPanel.repaint();
		}
	    }
	};
	animThread.start();
    }

    public void stop() {
	animThread = null;
    }
}
