package id.iptek.utms.agent.scheduler.job;

import id.iptek.utms.agent.dao.DownloadTaskDao;
import id.iptek.utms.agent.model.DownloadTask;
import id.iptek.utms.agent.model.enumeration.PublishTimeType;
import id.iptek.utms.agent.util.Singleton;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import org.quartz.Job;
import static org.quartz.JobBuilder.newJob;
import org.quartz.JobDataMap;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 *
 * @author jakar
 */
public class DownloadTaskSchedulerJob implements Job {

    private final Logger logger = LoggerFactory.getLogger(getClass());
    private DownloadTaskDao dao = new DownloadTaskDao();
    
    public DownloadTaskSchedulerJob() {
    }

    @Override
    public void execute(JobExecutionContext jec) throws JobExecutionException {
        try {
            logger.info("Execute job ..");
            List<DownloadTask> tasks = dao.getUnscheduledTasks();
            logger.info("Done query");
            logger.info("Got {} tasks", tasks.size());
            /*List<String> scheduledJobIds = (List<String>) Singleton.getInstance("SCHEDULER_JOBS").getObject();
            if(scheduledJobIds == null) {
                scheduledJobIds = new ArrayList<>();
                Singleton.getInstance("SCHEDULER_JOBS").setObject(scheduledJobIds);
            }*/
            for(DownloadTask task : tasks) {
                /*if(scheduledJobIds.contains(task.getId())) {
                    logger.info("Download Task with id '{}' is already scheduled.", task.getId());
                } else {
                    logger.info("Will schedule download task with id: {}", task.getId());
                    scheduleTask(task);
                    scheduledJobIds.add(task.getId());
                }*/
                
                logger.info("Will schedule download task with id: {}", task.getId());
                scheduleTask(task);
            }
        } catch(Exception ex) {
            logger.error("Error get tasks: {}", ex.getMessage(), ex);
        } finally {}
    }
    
    private void scheduleTask(DownloadTask task) throws SchedulerException {
        // get quartz scheduler
        Scheduler sched = (Scheduler) Singleton.getInstance("SCHEDULER").getObject();
        JobKey jobkey = new JobKey("download-task-" + task.getId(), "publish-task");
        if(sched.checkExists(jobkey)) return;
        
        if(task.getPublishTimeType() == PublishTimeType.IMMEDIATE) {
            // publish job in next 1 minutes
            JobDataMap map = new JobDataMap();
            map.put("task", task);
            JobDetail job = newJob(DownloadTaskPublisherJob.class)
                .withIdentity(jobkey)
                .usingJobData(map)
                .build();
            Calendar time = Calendar.getInstance();
            time.add(Calendar.MINUTE, 1);
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity("download-task-trigger-" + task.getId(), "publish-task")
                    .startAt(time.getTime())
                    .build();
            sched.scheduleJob(job, trigger);
            
            logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
        } else if(task.getPublishTimeType() == PublishTimeType.DATE_TIME) {
            Calendar time = Calendar.getInstance();
            // compare publish time with current time
            Date publishTime = task.getPublishTime();
            JobDataMap map = new JobDataMap();
            map.put("task", task);
            JobDetail job = newJob(DownloadTaskPublisherJob.class)
                .withIdentity(jobkey)
                .usingJobData(map)
                .build();
            if(time.getTime().equals(publishTime) || time.getTime().after(publishTime)) {
                // publish it next 5 minutes
                time.add(Calendar.MINUTE, 1);
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity("download-task-trigger-" + task.getId(), "publish-task")
                        .startAt(time.getTime())
                        .build();
                sched.scheduleJob(job, trigger);
                
                logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
            } else {
                Trigger trigger = TriggerBuilder.newTrigger()
                        .withIdentity("download-task-trigger-" + task.getId(), "publish-task")
                        .startAt(publishTime)
                        .build();
                sched.scheduleJob(job, trigger);
                
                logger.info("Task id-{} scheduled @{}", task.getId(), trigger.getFinalFireTime());
            }
        }
    } 
}
