package org.treesched.schedules;

import java.io.Serializable;
import java.util.Date;

import org.apache.log4j.Logger;
import org.treesched.AbstractSchedule;
import org.treesched.DateUtils;
import org.treesched.Interval;

/**
 * This schedule counts the occurence's of it's child schedule
 * and returns the required occurence.
 * <p>
 * Typical configuration is:
 * <code><pre>
 * &lt;occurrence occurrence="2"&gt;
 *   &lt;weekly/&gt;
 * &lt;/occurrence&gt;
 * </pre></code>
 * 
 * @author Rob Gordon
 */

final public class OccurrenceSchedule extends AbstractSchedule implements Serializable {

    private static final long serialVersionUID = 20050226;
    
    private final static Logger logger = Logger.getLogger(OccurrenceSchedule.class);
	private int occurrence;
	
	/**
	 * Set the number of the occurrence for this schedule.
	 * 
	 * @param occurrence The occurence.
	 */
	
	public void setOccurrence(String occurrence) {
		this.occurrence = Integer.parseInt(occurrence);
	}

	/**
	 * Return the number of the occurrence for this schedule.
	 * 
	 * @return The occurrence.
	 */
	
	public String getOccurrence() {		
		return Integer.toString(occurrence);
	}
	
	/**
	 * Return the next due interval which is the given occurrence of
	 * it's child schedules.
	 */
	
	public Interval nextDue(Date now) {
		if (now == null) {
		    throw new NullPointerException();
		}
		if (getChildSchedule() == null) {
		    throw new IllegalStateException("Occurence must have a child schedule.");
		}

		logger.debug(this + ": in Date is " + now);
		
	    Date use = now;
	    // start from the beginning interval of our parent, if there is one.
		if (getLimits() != null) {
		    use = getLimits().getFromDate();
		}
		Interval candidate = null;
		
		for (int i = 0; i < occurrence && use != null; ++i) {
			logger.debug(this + ": use interval is " + use);
			getChildSchedule().setLimits(getLimits());
			candidate = getChildSchedule().nextDue(use);
			
			if (candidate != null) {
				use = DateUtils.oneMillisAfter(candidate.getToDate());
			}
			else {				
				// break the cycle
				use = null;
			}
		}
		return candidate;
	}

	/**
	 * Override toString.
	 */
	
	public String toString() {
		
		return "Occurence Schedule, occurences " + getOccurrence();
	}
}
