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

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

class      Raster 
implements ImageObserver 
{
    protected int     width;
	protected int     height;
    protected int     pixel[];
    private   boolean available;  // for indicating image download status




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


    /**
     *  This constructor creates an uninitialized
     *  Raster Object of a given size (w x h).
     */
    public Raster( int w, int h )
	{
		width  = w;
		height = h;
		pixel  = new int[w*h];
    }


    /**
     *  This constructor creates an Raster initialized
     *  with the contents of an image.
     */
    public Raster( Image img )
    {
        width  = img.getWidth( this );
        height = img.getHeight( this );

        try {
        	if ( ( width < 0 ) || ( height < 0 ) ) {
            	available = false;
            	while (!available) {
            		Thread.sleep((long) 100);
					System.out.println( "Sleeping for image" );
            	}
         	}
			
          pixel = new int[width*height];
		  
          PixelGrabber grabber = new PixelGrabber( img,
		  										   0,
												   0,
												   width,
												   height,
												   pixel,
												   0,
												   width);
          grabber.grabPixels();
        } catch ( InterruptedException e ) {
          width  = 0;
          height = 0;
          pixel  = null;
          return;
        }
    }

    public boolean 
	imageUpdate( Image img, int flags, int x, int y, int w, int h )
    {
        if ( (flags & WIDTH)  != 0) width  = w;
        if ( (flags & HEIGHT) != 0) height = h;
        available = ( (width >= 0) && (height >= 0) );
        return !available;
    }


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

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getSize() 
	{
    	return pixel.length;
    }

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getWidth() 
	{
    	return width;
    }

    /**
     *  Returns the number of pixels in the Raster
     */
    public int getHeight() 
	{
    	return height;
    }

    public int[] 
	getPixelBuffer() 
	{
    	return pixel;
    }

    /**
     *  Fills a Raster with a solid color
     */
    public void 
	fill( int argb )
	{
    	int s = pixel.length;
    	for (int i = 0; i < s; i++) {
    		pixel[i] = argb;
		}
    }


    public void 
	fill( Color c ) 
	{
    	fill(c.getRGB());
    }


    /**
     *  Converts Rasters to Images
     */
    public Image 
	toImage( Component root )
	{
		return root.createImage( new MemoryImageSource( width, 
	  													height, 
														pixel, 
														0, 
														width) );
    }


    /**
     * The following helper routine
     * test that x and y are valid
     */
    private final boolean 
	invalid( int x, int y ) 
	{
    	return ( ( x < 0       ) ||
				 ( x >= width  ) || 
				 ( y < 0       ) ||  
				 ( y >= height ) );
    }

    /**
     *  Get a pixel from a Raster
     */
    public int 
	getPixel( int x, int y )
	{
		if ( invalid( x, y ) )
			return 0;
		else
			return pixel[y*width+x];
    }

    /**
     *  Get a color from a Raster
     */
    public Color 
	getColor( int x, int y ) 
	{
		return new Color( getPixel(x,y) );
    }

    /**
     *  Set a pixel to a given value
     */
    public boolean 
	setPixel( int pix, int x, int y ) 
	{
    	if ( invalid( x, y ) ) {
    		return false;
    	} else {
			pixel[y*width+x] = pix;
			return true;
		}
    }


    /**
     *  Set a pixel to a given color
     */
    public boolean 
	setColor( Color c, int x, int y )
	{
		return setPixel( c.getRGB(), x, y );
    }
}
