package com.cku.oa.timedtask.service;

import java.util.Date;
import java.util.Objects;

import org.quartz.Job;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.support.CronTrigger;
import org.springframework.scheduling.support.SimpleTriggerContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.support.DefaultTransactionDefinition;
import org.springframework.web.context.support.SpringBeanAutowiringSupport;

import com.cku.oa.sys.entity.TaskLog;
import com.cku.oa.sys.entity.TaskTrigger;
import com.cku.oa.sys.service.TaskLogService;
import com.cku.oa.sys.service.TaskTriggerService;
import com.thinkgem.jeesite.common.utils.DateUtils;
import com.thinkgem.jeesite.common.utils.IdGen;
import com.thinkgem.jeesite.modules.sys.entity.User;

/**
 * 
 * <p>
 * Title:JobActingService
 * </p>
 * <p>
 * Description: 任务调度代理
 * </p>
 * <p>
 * Company:
 * </p>
 * 
 * @author zhuoHeng
 * @date 2017年4月1日 下午4:01:58
 */
@Service
@Transactional(readOnly = true)
public abstract class JobActingService implements Job {

	@Autowired
	private TaskLogService taskLogService;

	@Autowired
	private TaskTriggerService taskTriggerService;

	@Autowired
	// private DataSourceTransactionManager transactionManager =
	// SpringContextHolder.getBean("TaskTriggerService");
	private DataSourceTransactionManager transactionManager;

	@Transactional(readOnly = false)
	abstract int doJob();

	@Transactional(readOnly = false)
	abstract public int executeOnce();

	@Transactional(readOnly = false)
	public void execute(JobExecutionContext context) throws JobExecutionException {

		SpringBeanAutowiringSupport.processInjectionBasedOnCurrentContext(this);

		int i = taskTriggerService.renewExecuteState("1", context.getJobDetail().getKey().getName());

		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
		TransactionStatus status = transactionManager.getTransaction(def);
		try {
			int countExecute = beforeExecute(context);
			if (countExecute == 0 && i == 1) {
				// 取消依照日期校验是否重复执行的条件，解决当天多次执行的任务只执行一次的BUG
				int count = doJob();
				try {
					jobLog(context, count);
				} catch (Exception e) {
					e.printStackTrace();
				}
			} else {
				taskTriggerService.renewExecuteState("0", context.getJobDetail().getKey().getName());
			}
		} catch (Exception ex) {
			transactionManager.rollback(status);
			throw ex;
		}
		transactionManager.commit(status);
	}

	/**
	 * 
	 * @Description：计划任务执行之前校验（防止重复执行） @author: zhuoHeng
	 * @version: 2017年4月5日 上午10:26:38
	 */
	@Transactional(readOnly = false)
	public int beforeExecute(JobExecutionContext context) {
		JobDetail jobDetail = context.getJobDetail();
		int count = 0;
		if (Objects.nonNull(jobDetail)) {
			TaskLog taskLog = taskLogService.validateExecute(jobDetail.getKey().getName());
			TaskTrigger tt = taskTriggerService.getExecuteState(context.getJobDetail().getKey().getName());
			Date nextExeTime = getNextExeTime(tt.getTimeFormat());
			if (Objects.nonNull(taskLog)
					&& DateUtils.formatDate(taskLog.getExecuteTime(), "yyyy-MM-dd HH:mm")
							.equals(DateUtils.formatDate(nextExeTime, "yyyy-MM-dd HH:mm"))
					&& DateUtils.getDate().equals(DateUtils.formatDate(nextExeTime, "yyyy-MM-dd"))) {
				count = 1;
			}
		}
		return count;
	}

	public Date getNextExeTime(String cron) {
		SimpleTriggerContext cxt = new SimpleTriggerContext();
		CronTrigger cronTrigger = new CronTrigger(cron);
		return cronTrigger.nextExecutionTime(cxt);
	}

	/**
	 * 
	 * @Description：调度任务执行日志
	 * @author: zhuoHeng
	 * @version: 2017年3月31日 下午1:53:12
	 */
	@Transactional(readOnly = false)
	public void jobLog(JobExecutionContext context, int count) throws Exception {

		DefaultTransactionDefinition def = new DefaultTransactionDefinition();
		def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

		TransactionStatus status = transactionManager.getTransaction(def);
		try {
			JobDetail jobDetail = context.getJobDetail();
			TaskLog taskLog = new TaskLog();
			Date date = new Date();
			taskLog.setId(IdGen.uuid());
			taskLog.setIsNewRecord(true);
			taskLog.preInsert();
			taskLog.setJobInfo(jobDetail.getJobDataMap().getString("jobInfo"));
			taskLog.setJobName(jobDetail.getKey().getName());
			taskLog.setJobGroup(jobDetail.getKey().getGroup());
			taskLog.setExecuteType("0");
			taskLog.setExecuteTime(date);
			taskLog.setSuccessCount(String.valueOf(count == -1 ? 0 : count));
			taskLog.setSuccessState(String.valueOf(count == -1 ? 1 : 0));
			taskLog.setCreateDate(date);
			taskLog.setUpdateDate(date);
			taskLog.setDelFlag("0");
			taskLog.setCreateBy(new User());
			taskLog.setUpdateBy(new User());
			taskLogService.addLog(taskLog);
			taskTriggerService.renewExecuteTime(jobDetail.getKey().getName(), date);
			taskTriggerService.renewExecuteState("0", jobDetail.getKey().getName());
		} catch (Exception ex) {
			transactionManager.rollback(status);
			throw ex;
		}
		transactionManager.commit(status);
	}

}
