import java.awt.Image;
import java.awt.Rectangle;
import java.awt.image.*;
import java.util.Vector;

public abstract class ImageFrameProducer implements ImageProducer {
    protected Vector consumers;
    protected int dst[];
    protected int dstW, dstH;
    protected int clipX, clipY, clipW, clipH;
    private static ColorModel defaultRGB = ColorModel.getRGBdefault();

    public ImageFrameProducer(int dstW, int dstH) {
	this.dstW = dstW;
	this.dstH = dstH;
	dst = new int[dstW * dstH];
	consumers = new Vector();
    }

    /*
     * Overload from subclass.
     * update() convert dst raster image.
     * It returns repaint clip region. null region means whole region.
     */
    protected abstract boolean update();

    public void produce() {
	for(int i = consumers.size() - 1; i >= 0; i--)
	    produce((ImageConsumer)consumers.elementAt(i));
    }

    public synchronized void addConsumer(ImageConsumer ic) {
	consumers.addElement(ic);
	ic.setDimensions(dstW, dstH);
	ic.setHints(ImageConsumer.SINGLEPASS);
    }

    public synchronized boolean isConsumer(ImageConsumer ic) {
	return consumers.contains(ic);
    }

    public synchronized void removeConsumer(ImageConsumer ic) {
	consumers.removeElement(ic);
    }

    public void startProduction(ImageConsumer ic) {
	if(!isConsumer(ic))
	    addConsumer(ic);
	produce();
    }

    public void requestTopDownLeftRightResend(ImageConsumer ic) {
	// Not needed.  The data is always in TDLR format.
    }

    protected void produce(ImageConsumer ic) {
	clipX = 0;
	clipY = 0;
	clipW = dstW;
	clipH = dstH;
	if(!update()) {
	    ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
	    return;
	}
	ic.setPixels(clipX, clipY, clipW, clipH,
		     defaultRGB, dst, dstW * clipY + clipX, dstW);
	ic.imageComplete(ImageConsumer.SINGLEFRAMEDONE);
    }
}
