package speiger.src.coreengine.utils.counters.timers;

import speiger.src.coreengine.utils.counters.averager.RunningAvg;

/**
 * Found this code on the Internet here:
 * http://forum.lwjgl.org/index.php?topic=6582.0
 *
 * @author Riven
 * @author kappaOne
 * 
 * @author Speiger (Adjusted original code to work with my system)
 */
public class FrameSyncer {
	long nextFrame = 0;
	boolean initialised = false;
	RunningAvg sleepDurations = new RunningAvg(10);
	RunningAvg yieldDurations = new RunningAvg(10);
	
	public void sync(int fps) {
		if(fps <= 0) { return; }
		if(!initialised) {
			initialised = true;
			sleepDurations.init(1000000);
			yieldDurations.init((int)(-(System.nanoTime() - System.nanoTime()) * 1.333));
			nextFrame = System.nanoTime();
		}
		try {
			for(long t0 = System.nanoTime(),t1;(nextFrame - t0) > sleepDurations.avg();t0 = t1) {
				Thread.sleep(1);// sleep time
				sleepDurations.add((t1 = System.nanoTime()) - t0); // update average
			}
			sleepDurations.dampenForLowResTicker();
			
			for(long t0 = System.nanoTime(),t1;(nextFrame - t0) > yieldDurations.avg();t0 = t1) {
				Thread.yield();// yield time
				yieldDurations.add((t1 = System.nanoTime()) - t0); // update average
			}
		}
		catch(InterruptedException e) {}
		nextFrame = Math.max(nextFrame + 1000000000L / fps, System.nanoTime());
	}
}