package com.jasamedika.medifirst2000.asynctask.timer;

import java.util.Calendar;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class LogbookVerificationTimer {
	private final static Logger LOGGER = LoggerFactory.getLogger(LogbookVerificationTimer.class);

	// What to do
	private final Runnable whatToDo;

	// when
	private final int dayOfMonth;
	private final int hourOfDay;
	private final int minuteOfHour;

	// The current timer
	private Timer current = new Timer();

	public void cancelCurrent() {
		LOGGER.info("LogbookVerificationTimer : Cancel current execution");
		current.cancel();

		LOGGER.info("LogbookVerificationTimer : Removes the timertask so it can be garbage collected");
		current.purge();
	}

	public static LogbookVerificationTimer schedule(Runnable runnable, int dayOfMonth, int hourOfDay, int minuteOfHour) {
		LOGGER.info("LogbookVerificationTimer : Create a new instance");
		return new LogbookVerificationTimer(runnable, dayOfMonth, hourOfDay, minuteOfHour);
	}

	private LogbookVerificationTimer(Runnable runnable, int day, int hour, int minute) {
		this.whatToDo = runnable;
		this.dayOfMonth = day;
		this.hourOfDay = hour;
		this.minuteOfHour = minute;

		schedule();
	}

	private void schedule() {
		cancelCurrent();

		LOGGER.info(
				"LogbookVerificationTimer : Assigning a new instance of Timer, allow the previous Timer to be garbage collected");
		current = new Timer();
		current.schedule(new TimerTask() {
			public void run() {
				try {
					LOGGER.info("LogbookVerificationTimer : Running schedule");
					whatToDo.run();
				} finally {
					LOGGER.info("LogbookVerificationTimer : Schedule for the next month");
					schedule();
				}
			}
		}, nextDate());
	}

	private Date nextDate() {
		Calendar curDate = Calendar.getInstance();
		Calendar runDate = Calendar.getInstance();

		// set_for_compare
		runDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
		runDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
		runDate.set(Calendar.MINUTE, minuteOfHour);
		runDate.set(Calendar.SECOND, 0);
		runDate.set(Calendar.MILLISECOND, 0);

		if (curDate.getTime().after(runDate.getTime())) {
			runDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
			runDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
			runDate.set(Calendar.MINUTE, minuteOfHour);
			runDate.set(Calendar.SECOND, 0);
			runDate.set(Calendar.MILLISECOND, 0);
			runDate.add(Calendar.MONTH, 1);
		}

		LOGGER.info("LogbookVerificationTimer : Set to next month " + runDate.getTime());

		return runDate.getTime();
	}
}
