package org.jblooming.agenda;
import net.sf.json.JSONObject;
import java.util.*;
public class ScheduleYearly extends ScheduleSupport implements Schedule {
private int dayOfWeek;
private int weekOfMonth;
public ScheduleYearly() {
}
public ScheduleYearly(Date start, int duration, int freq, int rep, boolean onlyWorkingDays) {
this(0, 0, start, duration, freq, rep, onlyWorkingDays);
}
public ScheduleYearly(int dayOfWeek, int weekOfMonth, Date start, int duration, int freq, int rep, boolean onlyWorkingDays) {
this.dayOfWeek = dayOfWeek;
this.weekOfMonth = weekOfMonth;
this.setStart(start);
this.setDuration(duration);
this.setRepeat(rep);
this.setFreq(freq > 0 ? freq : 1);
this.setOnlyWorkingDays(onlyWorkingDays);
recalculateFields();
}
protected int getDayOfWeek() {
return dayOfWeek;
}
protected void setDayOfWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
}
protected int getWeekOfMonth() {
return weekOfMonth;
}
protected void setWeekOfMonth(int weekOfMonth) {
this.weekOfMonth = weekOfMonth;
}
public int getDayInWeek() {
return dayOfWeek;
}
public void setDayInWeek(int dayOfWeek) {
this.dayOfWeek = dayOfWeek;
recalculateFields();
}
public int getWeekInMonth() {
return weekOfMonth;
}
public void setWeekInMonth(int weekOfMonth) {
this.weekOfMonth = weekOfMonth;
recalculateFields();
}
public void recalculateFields() {
CompanyCalendar cal = new CompanyCalendar();
cal.setTimeInMillis(this.getValidityStartTime());
this.setStartTime(cal.getMillisFromMidnight());
// first check if start is congruent with
adjustToDay(cal);
this.setStart(cal.getTime());
if (this.getRepeat() > 0) {
int freq = (this.getFreq() > 0 ? this.getFreq() : 1);
int val = (this.getRepeat() - 1) * freq;
cal.add(CompanyCalendar.YEAR, val);
adjustToDay(cal);
} else {
cal.setTime(CompanyCalendar.MAX_DATE);
cal.set(Calendar.HOUR_OF_DAY, 0);
cal.clear(Calendar.MINUTE);
cal.clear(Calendar.SECOND);
cal.clear(Calendar.MILLISECOND);
cal.add(Calendar.MILLISECOND, this.getStartTime());
}
cal.add(Calendar.MILLISECOND, (int) this.getDuration());
this.setEnd(cal.getTime());
}
public long getNextFireTimeAfter(long afterTime) {
long returnTime = Long.MAX_VALUE;
if (afterTime <= getEnd().getTime()) {
if (afterTime > getStart().getTime()) {
long lstart = getStart().getTime();
CompanyCalendar cal = new CompanyCalendar();
cal.setTimeInMillis(lstart);
int startYear = cal.get(CompanyCalendar.YEAR);
cal.setTimeInMillis(afterTime);
long distInYear = cal.get(CompanyCalendar.YEAR) - startYear;
int rep = 1;
int freq = (this.getFreq() > 0 ? this.getFreq() : 1);
if (distInYear > 0) {
rep = (int) distInYear / freq;
if ((distInYear % freq) != 0)
rep++;
}
if (this.getRepeat() > 0 && rep > (this.getRepeat() - 1))
rep = this.getRepeat() - 1;
cal.setTime(getStart());
cal.add(Calendar.YEAR, rep * freq);
adjustToDay(cal);
if (cal.getTime().getTime() <= afterTime) {
cal.add(Calendar.YEAR, freq);
adjustToDay(cal);
}
returnTime = cal.getTimeInMillis();
} else {
returnTime = getStart().getTime();
}
}
return returnTime;
}
private void adjustToDay(CompanyCalendar cal) {
if (weekOfMonth > 0 && dayOfWeek > 0) {
if (weekOfMonth == 5) {
cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, -1);
} else {
cal.set(Calendar.DAY_OF_WEEK, dayOfWeek);
cal.set(Calendar.DAY_OF_WEEK_IN_MONTH, weekOfMonth);
}
}
}
public long getPreviousFireTimeBefore(long beforeTime) {
long returnTime = Long.MIN_VALUE;
if (beforeTime > getStart().getTime()) {
if (beforeTime > getEnd().getTime())
beforeTime = getEnd().getTime();
long lstart = getStart().getTime();
CompanyCalendar cal = new CompanyCalendar();
cal.setTimeInMillis(lstart);
int startYear = cal.get(CompanyCalendar.YEAR);
cal.setTimeInMillis(beforeTime);
long distInYear = cal.get(CompanyCalendar.YEAR) - startYear;
int freq = (this.getFreq() > 0 ? this.getFreq() : 1);
int rep = (int) distInYear / freq;
if (this.getRepeat() == 0 || rep <= (this.getRepeat() - 1)) {
cal.setTime(getStart());
cal.add(Calendar.YEAR, rep * freq);
adjustToDay(cal);
if (cal.getTime().getTime() > beforeTime) {
cal.add(Calendar.YEAR, -freq);
adjustToDay(cal);
}
returnTime = cal.getTimeInMillis();
}
}
return returnTime;
}
public String getName() {
return "yearly";
}
public JSONObject jsonify() {
JSONObject ret = super.jsonify();
ret.element("type","yearly");
ret.element("dayOfWeek",getDayOfWeek());
ret.element("weekOfMonth",getWeekOfMonth());
return ret;
}
}