package cn.service.impl;

import java.math.BigInteger;
import java.util.Arrays;
import java.util.List;
import javax.annotation.Resource;
import org.quartz.JobDataMap;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Transactional;

import cn.constant.ScheduleConst;
import cn.orm.abs.ISqlToyDao;
import cn.orm.sqltoy.plus.Wrappers;
import cn.orm.sqltoy.plus.query.LambdaQueryWrapper;
import cn.orm.sqltoy.plus.query.QueryWrapper;
import cn.orm.sqltoy.plus.update.LambdaUpdateWrapper;
import cn.pojo.entity.TSysJob;
import cn.schedule.util.ScheduleUtil;
import cn.service.IJobService;
import cn.util.core.IsKit;
import cn.util.core.LogKit;

@Repository("IJobService")
public class JobServiceImpl implements IJobService
{
	@Resource
	private ISqlToyDao daoService;
	@Autowired
	private Scheduler scheduler;

	/**
	 * 任务调度状态修改
	 * @param job 调度信息
	 */	
	@Override
	public Boolean updateJobStatus(TSysJob job) 
	{
		String status = job.getStatus();
		Boolean result = false;
		//正常
		if (ScheduleConst.Status.NORMAL.getValue().equals(status)) {
			result = resumeJob(job);
		}
		//暂停
		else if (ScheduleConst.Status.PAUSE.getValue().equals(status)) {
			result = pauseJob(job);
		}
		return result;
	}
	/**
	 * 恢复任务
	 * @param job 调度信息
	 */
	public Boolean resumeJob(TSysJob job)
	{
		LambdaUpdateWrapper<TSysJob> updateWrapper = Wrappers.lambdaUpdateWrapper(TSysJob.class)
				.set(TSysJob::getStatus,ScheduleConst.Status.NORMAL.getValue())
				.eq(TSysJob::getJobId, job.getJobId());
		Long rows = daoService.update(updateWrapper);
		if (rows > 0) {
			try {
				scheduler.resumeJob(ScheduleUtil.getJobKey(job.getJobId(),job.getJobGroup()));
				return true;
			} catch (SchedulerException e) {
				LogKit.error(e);
			}
		}
		return false;
	}
	/**
	 * 暂停任务
	 * @param job 调度信息
	 */
	public Boolean pauseJob(TSysJob job) 
	{
		LambdaUpdateWrapper<TSysJob> updateWrapper = Wrappers.lambdaUpdateWrapper(TSysJob.class)
				.set(TSysJob::getStatus,ScheduleConst.Status.PAUSE.getValue())
				.eq(TSysJob::getJobId, job.getJobId());
		Long rows = daoService.update(updateWrapper);
		if (rows > 0) {
			try {
				scheduler.pauseJob(ScheduleUtil.getJobKey(job.getJobId(), job.getJobGroup()));
				return true;
			} catch (SchedulerException e) {
				LogKit.error(e);
			}
		}
		return false;
	}
	/**
	 * 更新任务的时间表达式
	 * @param job 调度信息
	 */
	@Override
	public Long updateJob(TSysJob job) throws Exception 
	{
		LambdaUpdateWrapper<TSysJob> updateWrapper = Wrappers.lambdaUpdateWrapper(TSysJob.class)
				.eq(TSysJob::getJobId, job.getJobId());
		Long rows = daoService.update(job,updateWrapper);
		//更新任务
		if (rows > 0) {
			updateSchedulerJob(job, job.getJobGroup());
		}
		return rows;
	}
	/**
	 * 更新任务
	 * @param job      任务对象
	 * @param jobGroup 任务组名
	 */
	private void updateSchedulerJob(TSysJob job, String jobGroup) throws Exception 
	{
		BigInteger jobId = job.getJobId();
		JobKey jobKey = ScheduleUtil.getJobKey(jobId, jobGroup);
		if (scheduler.checkExists(jobKey)) {
			// 防止创建时存在数据问题 先移除，然后在执行创建操作
			scheduler.deleteJob(jobKey);
		}
		ScheduleUtil.createScheduleJob(scheduler, job);
	}	
	/**
	 * 新增任务
	 * @param job 调度信息 调度信息
	 */
	@Override
	public Boolean saveJob(TSysJob job) throws Exception
	{
		job.setStatus(ScheduleConst.Status.PAUSE.getValue());
		//单个对象保存, 返回主键
		Object jobId = daoService.save(job);
		if (IsKit.isNotNull(jobId)) {
			ScheduleUtil.createScheduleJob(scheduler,job);
		}
		return jobId != null;
	}
	/**
	 * 批量删除调度信息
	 * @param jobIds 需要删除的任务IDSysJob
	 * @return 结果
	 * @throws Exception 
	 */
	@Override
	public Boolean deleteJobs(String[] jobIds) throws Exception 
	{
		if (IsKit.isNotNull(jobIds))
		{
			LambdaQueryWrapper<TSysJob> queryWrapper = Wrappers.lambdaWrapper(TSysJob.class)
					.in(TSysJob::getJobId,Arrays.asList(jobIds)) ;
			List<TSysJob> jobList = daoService.findList(queryWrapper);
			if(IsKit.isNotNullOrEmpty(jobList)) {
				jobList.forEach(t -> {
					try {deleteJob(t);} catch (Exception e) {	
						LogKit.info(e);
					}
				});
			}				
		}
		return jobIds != null && jobIds.length > 0;
	}	
	public boolean deleteJob(TSysJob job) throws Exception 
	{
		LambdaQueryWrapper<TSysJob> wrapper = Wrappers.lambdaWrapper(TSysJob.class)
				.eq(TSysJob::getJobId, job.getJobId());
		Long rows = daoService.delete(wrapper);
		//删除任务后，所对应的trigger也将被删除
		if (rows > 0) {
			scheduler.deleteJob(ScheduleUtil.getJobKey(job.getJobId(),job.getJobGroup()));
		}
		return rows > 0; 
	}

	/**查询一条记录*/
	@Override
	public TSysJob queryJob(String tableName,String field,Object fieldValue)
	{
		QueryWrapper<TSysJob> queryWrapper = Wrappers.wrapper(TSysJob.class)
				.eq(field, fieldValue);
		return daoService.findOne(queryWrapper);
	}	
	@Override
	public TSysJob queryJob(Long fieldValue)
	{
		QueryWrapper<TSysJob> queryWrapper = Wrappers.wrapper(TSysJob.class)
				.eq("job_id", fieldValue);
		return daoService.findOne(queryWrapper);
	}
	/**
	 * 立即运行任务
	 * @param job 调度信息
	 * @throws SchedulerException
	 *  定时任务立即执行要求不影响其日常的常规触点执行，所以一般采用暴露给前端的接口完成。
	 */
	@Override
	@Transactional
	public void runJob(TSysJob job) throws SchedulerException
	{
		LambdaQueryWrapper<TSysJob> queryWrapper = Wrappers.lambdaWrapper(TSysJob.class)
				.eq(TSysJob::getJobId, job.getJobId())
				.eq(TSysJob::getJobGroup, job.getJobGroup());
		TSysJob properties = daoService.findOne(queryWrapper);
		// 参数
		JobDataMap dataMap = new JobDataMap();
		dataMap.put(ScheduleConst.TASK_PROPERTIES, properties);
		JobKey jobKey = ScheduleUtil.getJobKey(job.getJobId(),job.getJobGroup());
		//定时任务创建的sheduler
		scheduler.triggerJob(jobKey, dataMap);
	}
}
