import java.util.Vector;

/** Experimental class to divide a playfield into a number of sections
    in order to potentially speed up user interaction with the
    sprites. (Divsion of playfield allows object to search only search
    a subset of the Sprites on calls to touch(x,y))

    Class is still in Development and highly experimental.
*/
public class DividedPlayField extends PlayField {

  Vector[][] spriteMap;
  private int gridSize;
  
  /** DividedPlayField constructor for playfield of size w * h
    */
  public DividedPlayField(int w, int h) {
    super(w, h);
    gridSize = 100;
    spriteMap = new Vector[w/gridSize+1][h/gridSize+1];
    for (int i=0; i<spriteMap.length; i++) {
      for (int j=0; j < spriteMap[i].length; j++) {
	spriteMap[i][j] = new Vector();
      }
    }
  }

  /** PlayField addSprite method.
      @see PlayField#addSprite
  */
  public void addSprite(Sprite s) {
    Vector v = getVectors(s.getLocation(), s.getWidth(), s.getHeight());
    for (int i=0; i<v.size(); i++) {
      ((Vector)v.elementAt(i)).addElement(s);
    }
  }

  /** Helper method to return the set of vectors that hold the sprites
      in a given area of the field.
  */
  private Vector getVectors(Point p, int width, int height) {
    Vector v = new Vector();
    for (int h=p.getY()/gridSize; 
	 h < (p.getY()+height)/gridSize+1;
	 h++) {
      for (int w=p.getX()/gridSize; 
	   w < (p.getX()+width)/gridSize+1;
	   w++) {
	v.addElement(spriteMap[w][h]);
      }
    }
    return v;
  }
	
  /** SpriteListener locationChanged method.
      @see SpriteListener#locationChanged
  */
  public void locationChanged(Sprite s, Point oldPoint, Point newPoint) {
    Vector oldVectors = 
      getVectors(oldPoint, s.getWidth(), s.getHeight());
    Vector newVectors = 
      getVectors(newPoint, s.getWidth(), s.getHeight());
    boolean[] addToNew = new boolean[newVectors.size()];
    for (int i=0; i<addToNew.length; i++) {
      addToNew[i] = true;
    }
    boolean removeFromOld;
    for (int i=0;i<oldVectors.size();i++) {
      Vector oldV = (Vector) oldVectors.elementAt(i);
      removeFromOld = true;
      for (int j=0; j<newVectors.size();j++) {
	Vector newV = (Vector) newVectors.elementAt(j);
	if (oldV == newV) {
	  addToNew[j] = false;
	  removeFromOld = false;
	}
      }
      if (removeFromOld) oldV.removeElement(s);
    }
    for (int i=0;i<newVectors.size();i++) {
      Vector v = (Vector) newVectors.elementAt(i);
      if (addToNew[i]) v.addElement(s);
    }
  }

  /** PlayField touch method.
      @see PlayField#touch
  */
  public boolean touch(int x, int y) {
    int sx, sy;
    int mx = x/gridSize;
    int my = y/gridSize;
    boolean foundOne = false;
    if (mx < spriteMap.length &&
	my < spriteMap[mx].length) {
      Vector vec = spriteMap[mx][my];
      for (int i=0; i<vec.size(); i++) {
	Sprite s = (Sprite) vec.elementAt(i);
	// System.out.println("Checking " + s);
	sx = s.getLocation().getX();
	sy = s.getLocation().getY();
	if (x > sx && x < sx + s.getWidth() &&
	    y > sy && y < sy + s.getHeight()) {
	  if (s.touch(x-sx, y-sy)) foundOne = true;
	}
      }
    }
    return foundOne;
  }

}
