package ps1;

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

public class Playfield
{
  /* Declarations */
  private Vector sprites;  // Vector of all sprites on the page
  private Raster main;;    // Raster of the playfield's background.
  private Color backColor;
  private Image backImage;
  
  /**
   * This constructor takes 2 arguments specifying the
   * size of the applet's window area.
   * Defaults the background to all white.
   */
  public Playfield(int w, int h)
  {
    main = new Raster(w, h);
    main.fill(new Color(0xFFFFFF));
    sprites = new Vector(10, 3);
  }
  
  /**
   * This constructor takes an argument: the image 
   * specifying the playfield's background.
   */
  public Playfield(Image img)
  {
    main = new Raster(img);
    sprites = new Vector(10, 3);
  }
  
  ////////////////////////// Methods //////////////////////////
  
  /** 
   * Adds a sprite to the collection of sprites currently on the playfield.
   */
  public void addSprite(Sprite s)
  {
    sprites.addElement(s);
  }

  /**
   * Sets the background color.
   */
  public void setBackColor(Color c)
  {
    // NOTE: Right now erases the screen.
    main = new Raster(main.width, main.height);
    backColor = new Color(c.getRGB());
    main.fill(c);
  }

  /**
   * Sets the background image.
   */
  public void setBackImage(Image img)
  {
    // NOTE: Right now erases the screen.
    main = new Raster(img);
  }
  
  public void updateSprites(int maxx, int maxy)
  {
    // Declarations
    int i = 0;
    Sprite s;

    for(i=0;i<sprites.size();i++)
      {
	s = ((Sprite)sprites.elementAt(i));
	s.flip(maxx, maxy);
	s.shunt();
      }
  }

  /**
   * This method updates the playfield's raster, performing all the operations needed to 
   * get the raster image into the desired state.
   */
  public Image updateImage()
  {
    // Declarations
    int i, j, k, rwidth, rheight, sx, sy;
    Raster r, out;
    int outwidth, alpha, fgcolor, bgcolor;
    Sprite s;

    // For now, no z-ordering implemented, or alpha-blending
    try
      {
	// Copy the original Raster
	out = new Raster(main.width, main.height);
	System.arraycopy(main.pixel, 0, out.pixel, 0, main.width * main.height);
      }
    catch(ArrayIndexOutOfBoundsException e)
      {
	System.out.println("Here1");
	return null;
      }
    
    
    outwidth = out.width;

    // This renders sprites
    for(i=0;i<sprites.size();i++)
      {
	// Get the sprite's current raster
	s = ((Sprite)sprites.elementAt(i));

	try
	  {
	    r = s.getRaster();
	  }
	catch(UninitializedException e)
	  {
	    continue;
	  }
	
	// Get the dimensions of the sprite
	sx = s.get_x_position();
	sy = s.get_y_position();
	rwidth = r.width;
	rheight = r.height;

	// render it on top of the background
	for(j=0;j<rheight;j++)
	  {
	    for(k=0;k<rwidth;k++)
	      {
		alpha = (r.pixel[j*rwidth+k] >> 24) & 0xff;
		
		// this line implements transparency
		if(alpha == 0)
		  {
		    // pixel is transparent: don't modify the output pixel.
		  }
		// this is for opaque pixels
		else if(alpha == 255)
		  {
		    out.pixel[(j+sy)*outwidth+(k+sx)] = r.pixel[j*rwidth+k];
		  }
		// this deals with alpha blending. Assumes only one layer
		else
		  {
		    fgcolor = r.pixel[j*rwidth+k] & 0x00ffffff;
		    bgcolor = out.pixel[(j+sy)*outwidth+(k+sx)] & 0x00ffffff;
		    out.pixel[(j+sy)*outwidth+(k+sx)] = alpha*fgcolor + (1-alpha)*bgcolor;
		  }
	      }
	  }
      }
    
    return out.toImage();
  }
  
  public Sprite InSprite(int x_loc, int y_loc)
  {
    int i;
    
    for(i=0;i<sprites.size();i++)
      if(((Sprite)sprites.elementAt(i)).hitTest(x_loc, y_loc))
	return ((Sprite)sprites.elementAt(i));
    return null;
  }
}

