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

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

class      AnimatedSprite 
extends    Sprite
implements Runnable
{
    public  AnimationRule animation_rule;
    private Thread        animation_thread;
    
    private boolean animate = false;


    /**
     *  This constructor creates an Raster initialized
     *  with the contents of an image.
     */
    public AnimatedSprite( Image img, AnimationRule animation_rule )
    {
        super( img );
        this.animation_rule = animation_rule;
    }


    /**
     *  Draw the sprite on the input raster. Return the Rectangle
     *  that we modified.
     */
    public Rectangle[]
    draw( Raster raster )
    {
        Rectangle clips[]   = animation_rule.getCurrentClips();
        Point     offsets[] = animation_rule.getCurrentOffsets();
        
        for ( int c=0; c<clips.length; c++ ) {
            int   last_row    = clips[c].y + clips[c].height;
            int   last_column = clips[c].x + clips[c].width;
            Point offset      = offsets[c];
            
            for ( int i=clips[c].y; i<last_row; i++ ) {
                for( int j=clips[c].x; j<last_column; j++ ) {
                    if ( ( j < width ) && ( i < height ) &&
                         !isTransparent( pixel[i*width+j]  ) ) {
                        raster.setPixel( pixel[i*width+j], 
                                         x+j-clips[c].x+offset.x,
                                         y+i-clips[c].y+offset.y );
                    }
                }
            }
        }
        
        Rectangle modified_clips[] = new Rectangle[clips.length];
        
        for ( int i=0; i<clips.length; i++ ) {
            modified_clips[i] = new Rectangle( x + offsets[i].x,
                                               y + offsets[i].y,
                                               clips[i].width,
                                               clips[i].height );
        }
        
        return modified_clips;
    }


    /**
     *  Point to the next clip
     */
    public void
    next()
    {
        animation_rule.next();
    }


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


    /**
     *  Run
     */
    public void
    run()
    {
        while ( true ) {
            try {
                animation_thread.sleep( animation_rule.getCurrentDelay() );
            } catch ( Exception e ) {
                System.out.println( "AnimatedSprite exception in sleeping" );
                e.printStackTrace( System.out );
            }
            if ( animate ) {
                next();
            }
        }
    }


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