package org.treesched.examples;

import java.util.Date;

import org.treesched.DateUtils;
import org.treesched.Interval;
import org.treesched.Schedule;

/**
 * This class will do stuff when scheduled. Used by 
 * {@link CodeExample} but also shows how a treesched Schedule
 * could be used in a scheduler.
 */
public class SimpleScheduler implements Runnable {

	/** Flag to indicate stopping */
	private boolean stop = false;
	
	/** The schedule */
	private Schedule schedule;
	
	/**
	 * The do stuff method. If this were a more complicated scheduler this might
	 * execute registered job methods or fire events to listeners.
	 */
	public void doStuff() {		
		System.out.println("Doing stuff.");
	}

	/**
	 * Runs the scheduling on a separate thread.
	 */
	public void run() {
		
		Date scheduleFrom = new Date();
		while (!stop) {			
			Interval nextDue = schedule.nextDue(scheduleFrom);
			System.out.println("Next due: " + nextDue);

			// when the schedule ends, return.
			if (nextDue== null) {
				return;
			}

			long sleep = 0;

			// The thread might be woken before it's due so loop until it is due.
			do {	
				Date now = new Date();
				sleep = nextDue.getFromDate().getTime() - now.getTime();
	
				if (sleep > 0) {	
					try {
						synchronized (this) {
							wait(sleep);
						}
					}
					catch (InterruptedException e) {
						// ignore.
					}
				}
				
				if (stop) {
					// were we woken by the stop
					return;
				}
			} while (sleep > 0);
			
			doStuff();
			
			// This moves the schedule on.
			scheduleFrom = DateUtils.oneMillisAfter(nextDue.getToDate());
		}		
	}
	
	/**
	 * Set the schedule to use.
	 * 
	 * @param schedule The schedule.
	 */
	synchronized public void setSchedule(Schedule schedule) {
		this.schedule = schedule;	
	}
	
	/**
	 * Stop the scheduling.
	 */
	synchronized public void stop() {
		stop = true;
		notifyAll();
	}
}
