package mbOrbits;
import java.awt.image.*;

abstract public class MandComp {
	
	protected MandelbrotCanvas owner;
	protected WritableRaster raster;
	protected int imageWidth, imageHeight;
	protected double xmin, xmax, ymin, ymax;
	protected int maxIterations;
	protected boolean stretchPalette;
	
	private Thread runner;
	protected volatile boolean running;
	protected static volatile int drawCount;
	
	
	synchronized public void install(MandelbrotCanvas canvas) {
		install(canvas,0);
	}

	synchronized public void install(MandelbrotCanvas canvas, final int delay) {
		if (running)
			cancel();
		drawCount++;
    	owner = canvas;
    	if (canvas == null)
    		return;
    	owner.startedRunning();
    	BufferedImage image = owner.getImage();
    	imageWidth = image.getWidth();
    	imageHeight = image.getHeight();
    	raster = image.getRaster();
    	xmin = owner.getXmin();
    	xmax = owner.getXmax();
    	ymin = owner.getYmin();
    	ymax = owner.getYmax();
    	maxIterations = owner.getMaxIterations();
    	stretchPalette = false;
    	runner = new Thread() {
    		public void run() {
    			int myDrawCount = drawCount;
    			running = true;
    			if (delay > 0) {
    				try {
    					synchronized(MandComp.this) {
    						MandComp.this.wait(delay);
    					}
    				}
    				catch (InterruptedException e) {
    				}
    			}
    			else
    				Thread.yield();
    			try {
    				if (running && drawCount == myDrawCount)
    					MandComp.this.run(myDrawCount);
    			}
    			catch (Exception e) {
    			}
    			owner.doneRunning();
    			synchronized(MandComp.this) {
    				running = false;
    				owner = null;
    				MandComp.this.notify();
    			}
    		}
    	};
    	runner.start();
    }
	
	public boolean isRunning() {
		return running;
	}
    
    synchronized public void cancel() {
    	if (! running)
    		return;
    	if (runner != null) {
    		if (runner.isAlive()) {
    			running = false;
    			notify();
    			try {
    				wait(500);
    			}
    			catch (InterruptedException e) {
    			}
    		}
    		runner = null;
    	}
    }
    
    protected int countIterations(double x, double y) {
	   int count = 0;
	   double zx = x;
	   double zy = y;
	   while (count < maxIterations
	               && zx < 500 && zx > -500 && zy < 500 && zy > -500) {
	      double new_zx = zx*zx - zy*zy + x;
	      zy = 2*zx*zy + y;
	      zx = new_zx;
	      count++;
	   }
	   return count;    	
    }
    
	public int getIndexFor(int iterations) {
		if (iterations >= maxIterations)
			return 250;
		else if (stretchPalette)
			return (int)(250*((double)iterations)/maxIterations);
		else
			return iterations % 250;
	}
	
    abstract public void run(int myDrawCount);
	
}
