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;

/**
 * @author salmanoe
 * @since Dec 29, 2021
 */
public class TargetSkorDokterTimer {

	private final static Logger LOGGER = LoggerFactory.getLogger(TargetSkorDokterTimer.class);

	// What to do
	private final Runnable whatToDo;

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

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

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

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

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

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

		schedule();
	}

	private void schedule() {
		cancelCurrent();

		LOGGER.info(
				"TargetSkorDokterTimer : 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("TargetSkorDokterTimer : Running schedule");
					whatToDo.run();
				} finally {
					LOGGER.info("TargetSkorDokterTimer : Schedule for the next year");
					schedule();
				}
			}
		}, nextDate());
	}

	private Date nextDate() {
		Calendar runDate = Calendar.getInstance();
		runDate.set(Calendar.MONTH, 0);
		runDate.set(Calendar.DAY_OF_MONTH, dayOfMonth);
		runDate.set(Calendar.HOUR_OF_DAY, hourOfDay);
		runDate.set(Calendar.MINUTE, 0);
		runDate.set(Calendar.SECOND, 0);
		runDate.set(Calendar.MILLISECOND, 0);
		runDate.add(Calendar.YEAR, 1);

		LOGGER.info("TargetSkorDokterTimer : Set to next year " + runDate.getTime());

		return runDate.getTime();
	}

}
