package plots;

public abstract class AnimatedCanvas extends PlotCanvas implements Runnable {
	public int stepNo = 0, dS = 1;
	public double t = 0, dt = 1;
	Painter p;

	public AnimatedCanvas(int w, int h) {
		super(w, h);
		p = new Painter(this);
	}

	public void step() {
		t += dt;
		stepNo += dS;
	}
	
	public void reverse() {
		dt -= dt;
		dS = -dS;
	}

	public void setInterval(float dt) {
		this.dt = dt;
	}

	public void reset() {
		t = 0;
		stepNo = 0;
	}

	// ---------------------------------------------

	public boolean runnable = false;
	Thread T;
	public void start() {
		if (T == null) {
			runnable = true;
			T = new Thread(this);
			T.start();
		}
	}
	
	public void stop() {
		if (T != null) {
			runnable = false;
			T = null;
		}
	}
	
	public int ont = 50;
	public int napTime = ont;
	public void setNapTime(int n) {
		ont = n;
		napTime = n;
	}
	
	/* Sets the nap time to agree with drawing times. 
	   In the present version, it chooses the minimum drawing time
	   from the first five. */
	 
	void adjustTiming() {
		int s = ont, N = 5;
		// Time T = new Time();
		p.start(); 
		for (int i=0;runnable && N>0;i++) {
			if (p.isAsleep()) {
				N--;
				if (N > 2 && s < p.elapsedTime) {
					s = (int) p.elapsedTime;
				}
				render();
				p.start(); 
			}
			// T.mark();
			try {
				Thread.sleep(s);
			} catch (Exception e) {
				System.err.println("Unable to sleep!"); 
			}
		}
		napTime = s;
		// System.err.println("");
		// System.err.println("pause        = " + napTime);
		// System.err.println("last time to draw = " + p.elapsedTime);
	}
	
	public void run() {
		draw();
		adjustTiming();
		// Time T = new Time();
		while (runnable) {
			// T.mark();
			if (p.isAsleep()) {
				render();
				p.start();
			} 
			try {
				Thread.sleep(napTime);
			} catch (Exception e) { 
				System.err.println("Unable to sleep");
			}
		}
	}
}

class Painter implements Runnable  {
	AnimatedCanvas a;
	long elapsedTime;

	public Painter(AnimatedCanvas a) {
		this.a = a;
	}

	public void run() {
		long tinit = System.currentTimeMillis();
		a.step();
		a.draw();
		elapsedTime = System.currentTimeMillis() - tinit;
		t = null;
	}

	Thread t = null;
	public void start() {
		if (t == null) {
			t = new Thread(this);
			t.start();
		}
	}

	public boolean isPainting() {
		return (t != null);
	}

	public boolean isAsleep() {
		return (t == null);
	}
}
