import java.awt.Color;
import java.awt.Component;
import java.awt.Image;
import java.awt.Rectangle;

import java.awt.image.ImageObserver;
import java.awt.image.MemoryImageSource;
import java.awt.image.PixelGrabber;

class      Playfield
extends    Raster
implements Runnable
{
	public  Raster    rasters[];
	public  Rectangle old_patches[];
	private int       background[];
	private Thread    animation_thread;
	private Component component;
	
	private boolean animate = false;

    /**
     *  This constructor which takes no arguments
     *  allows for future extension.
     */
    public Playfield() 
	{
    }


    /**
     *  This constructor creates an uninitialized
     *  Raster Object of a given size (w x h).
     */
    public Playfield( int w, int h )
	{
		super( w, h );
    }


    /**
     *  This constructor creates an Raster initialized
     *  with the contents of an image.
     */
    public Playfield( Image img, Component component )
    {
		super( img );
		background = new int[pixel.length];
		System.arraycopy( pixel, 0, background, 0, pixel.length );
		this.component = component;
    }


    /**
     *  Add a new raster
     */
    public void
	addRaster( Raster raster )
    {
		if ( rasters == null ) {
			rasters        = new Raster[1];
			old_patches    = new Rectangle[1];
			rasters[0]     = raster;
			old_patches[0] = new Rectangle();
			return;
		}
		
		Raster    tmp_rasters[]     = new Raster[rasters.length+1];
		Rectangle tmp_old_patches[] = new Rectangle[rasters.length+1];
		
		for ( int i=0; i<rasters.length; i++ ) {
			tmp_rasters[i] = rasters[i];
			tmp_old_patches[i] = old_patches[i];
		}
		tmp_rasters[tmp_rasters.length-1]     = raster;
		tmp_old_patches[tmp_rasters.length-1] = new Rectangle();
		
		rasters     = tmp_rasters;
		old_patches = tmp_old_patches;
    }


    /**
     *  Draw the rasters
     */
    public void
	draw()
    {
		if ( rasters == null ) {
			return;
		}

		for ( int i=0; i<old_patches.length; i++ ) {
			for ( int row=old_patches[i].y; 
				  ( row<old_patches[i].y + old_patches[i].height) && 
				  ( row<height );
				  row++ ) {
				for ( int col=old_patches[i].x;
					  ( col<old_patches[i].x + old_patches[i].width) &&
					  ( col<width );
					  col++ ) {
					pixel[row*width + col] = background[row*width + col];
				}
			}
			Image clip_image = component.createImage( 
								   new MemoryImageSource ( 
								   	   old_patches[i].width,
								   	   old_patches[i].height,
									   background,
									   old_patches[i].y*width+old_patches[i].x,
									   width ) );
			component.getGraphics().drawImage( clip_image, 
											   old_patches[i].x, 
											   old_patches[i].y,
											   component );
		}
		
		for ( int i=0; i<rasters.length; i++ ) {
			if ( rasters[i] instanceof AnimatedSprite ) {
				old_patches[i] = ((AnimatedSprite)rasters[i]).draw( this );
				continue;
			}
			
			if ( rasters[i] instanceof Sprite ) {
				old_patches[i] = ((Sprite)rasters[i]).draw( this );
				continue;
			}
			
			if ( rasters[i] instanceof Raster ) {
				Raster raster = rasters[i];
				int    rows   = raster.getHeight();
				int    cols   = raster.getWidth();

				for ( int row=0; ( row<rows ) && ( row<height ); row++ ) {
					for ( int col=0; ( col<cols ) && ( row<width ); col++ ) {
						pixel[row*width + col] = raster.getPixel( col, row );
					}
				}
				old_patches[i] = new Rectangle( 0, 0, cols, rows );
				continue;
			}
		}
		
		for ( int i=0; i<old_patches.length; i++ ) {
			Image clip_image = component.createImage( 
								   new MemoryImageSource ( 
								   	   old_patches[i].width,
								   	   old_patches[i].height,
									   pixel,
									   old_patches[i].y*width+old_patches[i].x,
									   width ) );
			component.getGraphics().drawImage( clip_image, 
											   old_patches[i].x, 
											   old_patches[i].y,
											   component );
		}
    }


    /**
     *  Converts Rasters to Images
     */
    public Image 
	toImage( Component root )
	{
		System.out.println( "Width  = " + width );
		System.out.println( "Height = " + height );
		return root.createImage( new MemoryImageSource( width, 
	  													height, 
														pixel, 
														0, 
														width) );
    }


    /**
     *  Start animation
     */
    public void
	startAnimation()
    {
		System.out.println( "Starting the playfield MainAnimationThread" );
		animate          = true;
		animation_thread = new Thread( this, "MainAnimationThread" );
		animation_thread.start();
	}


    /**
     *  Run
     */
    public void
	run()
    {
		while ( true ) {
			try {
				animation_thread.sleep( 200l );
			} catch ( Exception e ) {
				System.out.println( "AnimatedSprite exception in sleeping" );
				e.printStackTrace( System.out );
			}
			if ( animate ) {
				System.out.println( "Rasterizing the playfield" );
				draw();
			}
		}
	}


    /**
     *  Stop animation
     */
    public void
	stopAnimation()
    {
		animate = false;
	}
}
