package net.northking.cctp.executePlan.quartz;

import net.northking.cctp.executePlan.constants.QuartzConstant;
import net.northking.cctp.executePlan.db.entity.AtuPlanInfo;
import org.apache.commons.lang3.StringUtils;
import org.quartz.*;
import org.quartz.impl.calendar.BaseCalendar;
import org.quartz.impl.triggers.CronTriggerImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Date;
import java.util.List;

/**
 * <p>Title: ScheduleService</p>
 * <p>Description: </p>
 *
 * @Author chenjianfeng
 * @Version V1.0
 * @Date 2022/12/29
 * <p>Copyright (c) 京北方信息技术股份有限公司 Corporation 2022 . All rights reserved.</p>
 */

public class ScheduleUtils {

    private final static Logger logger = LoggerFactory.getLogger(ScheduleUtils.class);

    /**
     * job是否存在
     * @param scheduler 调度器
     * @param jobId ID
     */
    public static Boolean checkExists(Scheduler scheduler, String jobId){
        return checkExists(scheduler, jobId, QuartzConstant.JOB_GROUP_DEFAULT);
    }

    /**
     * 创建定时任务
     * @param scheduler 调度器
     * @param planInfo 计划信息
     */
    public static void createScheduleJob(Scheduler scheduler, AtuPlanInfo planInfo){
        Class<? extends Job> jobClass = QuartzJobExecution.class;

        // 构建job信息
        String jobId = planInfo.getId();
        JobKey jobKey = getJobKey(jobId, QuartzConstant.JOB_GROUP_DEFAULT);
        JobDetail jobDetail = JobBuilder.newJob(jobClass).withIdentity(jobKey).build();

        //判空
        if(StringUtils.isBlank(planInfo.getCronExpr())){
            return;
        }
        // 表达式调度构建器
        CronScheduleBuilder cronScheduleBuilder = CronScheduleBuilder.cronSchedule(planInfo.getCronExpr());

        try {
            // 按新的cronExpression表达式构建一个新的trigger
            CronTrigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(getTriggerKey(jobId, QuartzConstant.JOB_GROUP_DEFAULT))
                    .withSchedule(cronScheduleBuilder)
                    .build();
            // 放入参数，运行时的方法可以获取
            jobDetail.getJobDataMap().put(QuartzConstant.PLAN_TASK_PROPERTIES, planInfo);

            // 判断是否存在
            if (scheduler.checkExists(jobKey))
            {
                // 防止创建时存在数据问题 先移除，然后在执行创建操作
                scheduler.deleteJob(jobKey);
            }

            Date firstRunTime = scheduler.scheduleJob(jobDetail, trigger);
            logger.info(jobDetail.getKey() + " 将运行于：" + firstRunTime);

        } catch (Exception e) {
            logger.error("创建Job失败", e);
        }
    }

    /**
     * job是否存在
     * @param scheduler 调度器
     * @param jobId ID
     * @param jobGroup group
     */
    public static Boolean checkExists(Scheduler scheduler, String jobId, String jobGroup){
        JobKey jobKey = getJobKey(jobId, jobGroup);
        try {
            return scheduler.checkExists(jobKey);
        }catch (Exception e){
            logger.error("删除Job失败", e);
        }
        return false;
    }

    /**
     * 删除job
     * @param scheduler 调度器
     * @param jobId ID
     */
    public static void deleteJob(Scheduler scheduler, String jobId){
        deleteJob(scheduler, jobId, QuartzConstant.JOB_GROUP_DEFAULT);
    }

    /**
     * 删除job
     * @param scheduler 调度器
     * @param jobId ID
     * @param jobGroup group
     */
    public static void deleteJob(Scheduler scheduler, String jobId, String jobGroup){
        JobKey jobKey = getJobKey(jobId, jobGroup);
        try {
            scheduler.deleteJob(jobKey);
        }catch (Exception e){
            logger.error("删除Job失败", e);
        }
    }

    /**
     * 获取下几次执行时间
     * @param cronExpr Cron表达式
     * @param num 次数
     * @return 结果集
     */
    public static List<Date> getNextTriggerTimes(String cronExpr, int num){
        try {
            CronTriggerImpl cronTrigger = new CronTriggerImpl();
            cronTrigger.setCronExpression(cronExpr);
            BaseCalendar cal = new BaseCalendar();
            return TriggerUtils.computeFireTimes(cronTrigger, cal, num);
        }catch (Exception e){
            logger.error("获取下几次执行时间失败", e);
        }
        return null;
    }

    /**
     * 获取下一次执行时间
     * @param cronExpr Cron表达式
     * @return 下一次执行时间
     */
    public static Date getNextOneTriggerTime(String cronExpr){
        List<Date> nextTriggerTimes = getNextTriggerTimes(cronExpr, 1);
        if (nextTriggerTimes != null && nextTriggerTimes.size() > 0){
            return nextTriggerTimes.get(0);
        }
        return null;
    }


    /**
     * 构建任务触发对象
     */
    public static TriggerKey getTriggerKey(String jobId, String jobGroup){
        return TriggerKey.triggerKey(QuartzConstant.PLAN_TASK_CLASS_NAME + jobId, jobGroup);
    }

    /**
     * 构建任务键对象
     */
    public static JobKey getJobKey(String jobId, String jobGroup)
    {
        return JobKey.jobKey(QuartzConstant.PLAN_TASK_CLASS_NAME + jobId, jobGroup);
    }
}
