package proj1b;

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

class Playfield extends Raster {
			// inherit: width, height, pixel[]

    ///////////////////// Private Variables /////////////////////

		       // The number of sprites on the field
    private int numSprites;
    public int currSprite;
    //private int currSprite;
    private int maxNumSprites;

    private static final int noSprite = -10;

		       // The array of sprites
    private Sprite [] sprites;

    ///////////////////////// Constructors //////////////////////

    /**
     *  This constructor creates a Playfield Object for an image
     *  Playfields start out with only a background, no sprites
     *  maxNumSpri holds the maximum number of expected sprites
     */
    public Playfield(Image image, int maxNumSpri)
    {
	super(image);                   // construct background first

	numSprites = 0;                 // init number Sprites
	currSprite = noSprite;          // Select no sprites to begin with

	if(maxNumSpri < 1) maxNumSpri = 1;
	maxNumSprites = maxNumSpri;     // init max number Sprites

	sprites = new Sprite[maxNumSpri];
	                                // array only when add Sprites
    }

    public Playfield(int maxNumSpri)
    {
	super();                        // construct Raster with null

	numSprites = 0;                 // init number Sprites
	currSprite = noSprite;          // Select no sprites to begin with

	if(maxNumSpri < 1) maxNumSpri = 1;
	maxNumSprites = maxNumSpri;     // init max number Sprites

	sprites = new Sprite[maxNumSpri];
	                                // array only when add Sprites
    }

    ////////////////////////// Methods //////////////////////////

    /**
     *  Adds a sprite to a given slot
     *  Return false if index is out of bounds or the slot is already
     *     taken. Note!!! Keep track of sprite positions, and use
     *     removeSprite(slot) first to replace sprites.
     *  The new sprite starts out at position 0,0
     *     Change its position before calling the Playfield draw() function
     *     and redisplaying the field. A more comprehensive version is below.
     *     Use this function when adding a number of sprites at once.
     */
    /********** temporarily private , possibly public later ************/
    private boolean addSprite(Image sImg, int slot)
    {
       // out of bounds index
       if (slot < 0 || slot >= maxNumSprites) return false;
	  
       if (sprites[slot] != null) return false;

       undraw();
       sprites[slot] = new Sprite(sImg);
       return true;
    }

    /**
     *  Adds a sprite to a given slot, gives it a start position, and
     *  draws the Playfield. Just need to redisplay after this function.
     */
    public boolean addSprite(Image sImg, int slot, int xP, int yP)
    {
       if (!addSprite(sImg, slot)) return false;

       sprites[slot].xPos = xP;
       sprites[slot].yPos = yP;
       draw();
       return true;
    }

    /**
     *  Remove a sprite from a given slot
     *  Return false if index is out of bounds or the slot is empty
     *  Call before putting a sprite into a slot if uncertain of its
     *     contents (and you dont care about them)
     *  If multiple sprites are on-screen, remember to undraw them
     *     in order before removing any from the screen!!!
     */
    public boolean removeSprite(int slot)
    {
       // out of bounds index
       if (slot < 0 || slot >= maxNumSprites) return false;
	  
       if (sprites[slot] == null) return false;

       undraw();
       sprites[slot] = null;
       draw();
       return true;
    }

    /**
     *  Draws the sprites onto the playfield. 
     *  Note that this does *not* display anything.
     */
    public void draw()
    {
       int idx;

       for(idx = 0; idx < maxNumSprites; idx++)
	  if(sprites[idx] != null) {
	     sprites[idx].draw(this); // the Playfield __IS__ the background
	                              // Overlap order: high overlaps low
	  }
    }

    /**
     *  Undraws the sprites. Note that this does *not* display anything.
     */
    public void undraw()
    {
       int idx;

       for(idx = maxNumSprites; idx-- > 0; )
	  if(sprites[idx] != null) {
	     sprites[idx].undraw(this); // the Playfield __IS__ the background
	                                // Overlap order: high overlaps low
	                                // thus, remove higher sprite first
	  }
    }

    /**
     *  Select the topmost sprite under the mouse. The sprite identity is
     *  stored in the Playfield. True is returned if the display has
     *  changed (redisplay Playfield then).
     */
    public boolean mouseSelect(int x, int y)
    {
       int idx;
       boolean changed = false;

       for(idx = maxNumSprites; idx-- > 0; ) {
// System.out.println("Idx " + idx + " " + (sprites[idx]==null?"NUL":"TRU") );
// if(sprites[idx]!=null)
// System.out.println("Idx inn" + (sprites[idx].isOn(x,y,this)?"YUL":"NRU") );
// else
// System.out.println("Idx inn" + "NULL");
          if(sprites[idx] != null && sprites[idx].isOn(x,y,this)) {
// System.out.println("CUrr " + currSprite + " idx " + idx );
	     if (currSprite != idx && currSprite != noSprite) {
		if(sprites[currSprite] != null) {
		   sprites[currSprite].deselect();
		   changed = true;
		}
		currSprite = noSprite;
	     }

	     if (currSprite == idx) { // if selected already, deselect
// System.out.println("Deselect " + idx);
		sprites[currSprite].deselect();
		currSprite = noSprite;
		changed = true;
             } else if (currSprite == noSprite) {
// System.out.println("Select " + idx);
		currSprite = idx;
		sprites[idx].select();
		changed = true;
	     }
	     break;
	  } // if we are on the sprite
       } // Find the topmost sprite under the mouse

       if (changed) { // Screen has changed, so repaint internally
	  undraw();
	  draw();
       }
       return changed;
    }

    /**
     *  If a sprite is selected, then drag it around the screen
     *  Return true if the image changes
     */
    public boolean mouseMove(int x, int y)
    {
       if(currSprite != noSprite) { // The sprite is moving, repaint
          if(sprites[currSprite] == null) {
	     currSprite = noSprite;
	     return false;
	  } // error check...

          undraw();
	  sprites[currSprite].xPos = x;
	  sprites[currSprite].yPos = y;
	  draw();
	  return true;
       } else {
	  return false;
       }
    }
}
