/*
 *  Copyright 2019-2020 Zheng Jie
 *
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 *
 *  http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */
package com.yfd.platform.modules.patroltask.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.yfd.platform.modules.patroltask.domain.TaskTodo;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.DirectSchedulerFactory;
import org.quartz.simpl.RAMJobStore;
import org.quartz.simpl.SimpleThreadPool;
import org.quartz.spi.JobStore;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @date 2023-04-28
 */
@Slf4j
@Component
public class QuartzMultiTaskManage {
    //巡视任务
    private static final String JOB_NAME = "PATROLTASK_";

    private static Map<String, Object> schedulers = new HashMap<String, Object>();
    //private static SimpleThreadPool threadPool = new SimpleThreadPool(20, Thread.NORM_PRIORITY);
    /**
     * 添加一个job
     *
     * @param todoJob /
     */
    public void addJob(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=null;
        try {
            if(ObjectUtil.isEmpty(schedulers.get(statisoncode))){
                DirectSchedulerFactory schedulerFactory = DirectSchedulerFactory.getInstance();
                SimpleThreadPool threadPool = new SimpleThreadPool(1, Thread.NORM_PRIORITY);
                threadPool.initialize();
                JobStore jobStore = new RAMJobStore();
                schedulerFactory.createScheduler(statisoncode, statisoncode, threadPool, jobStore);
                statisonScheduler=schedulerFactory.getScheduler(statisoncode);
                schedulers.put(statisoncode,statisonScheduler);
            }else{
                statisonScheduler=(Scheduler) schedulers.get(statisoncode);
            }
            // 构建job信息  任务按变电站分组
            JobDetail jobDetail = JobBuilder.newJob(TodoTaskJob.class).
                    withIdentity(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode()).build();

            Date plandate= DateUtil.parse(todoJob.getPlanStartTime(),"yyyy-MM-dd HH:mm:ss");
            // 创建触发器实例
            Trigger trigger = TriggerBuilder.newTrigger()
                    .withIdentity(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode())
                    .startAt(plandate) // 设置开始时间为指定的日期时间
                    .endAt(null) // 设置结束时间为 null
                    .withSchedule(SimpleScheduleBuilder.simpleSchedule()
                            .withRepeatCount(0) // 设置重复次数为 0
                            .withIntervalInSeconds(0) // 设置重复时间间隔为 0
                    )
                    .build();

            trigger.getJobDataMap().put(TaskTodo.JOB_KEY, todoJob);
            statisonScheduler.scheduleJob(jobDetail, trigger);
            statisonScheduler.start();
        } catch (Exception e) {
            log.error("添加定时任务失败", e);
            throw new RuntimeException("添加定时任务失败");
        }


  }

    /**
     * 删除一个job
     *
     * @param todoJob /
     */
    public void deleteJob(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=(Scheduler) schedulers.get(statisoncode);
        try {
            JobKey jobKey = JobKey.jobKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            statisonScheduler.pauseJob(jobKey);
            statisonScheduler.deleteJob(jobKey);
        } catch (Exception e) {
            log.error("删除定时任务失败", e);
            throw new RuntimeException("删除定时任务失败");
        }
    }

    /**
     * 中断一个执行中的任务
     *
     * @param todoJob /
     */
    public void interruptJob(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=(Scheduler) schedulers.get(statisoncode);
        try {
            JobKey jobKey = JobKey.jobKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            statisonScheduler.interrupt(jobKey);
                   } catch (Exception e) {
            log.error("中断正在执行中的任务", e);
            throw new RuntimeException("中断正在执行中的任务");
        }
    }

    /**
     * 恢复一个job
     *
     * @param todoJob /
     */
    public void resumeJob(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=(Scheduler) schedulers.get(statisoncode);
        try {
            TriggerKey triggerKey =
                    TriggerKey.triggerKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            Trigger trigger =
                    statisonScheduler.getTrigger(triggerKey);
            // 如果不存在则创建一个定时任务
            if (trigger == null) {
                addJob(todoJob);
            }
            JobKey jobKey = JobKey.jobKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            statisonScheduler.resumeJob(jobKey);
        } catch (Exception e) {
            log.error("恢复定时任务失败", e);
            throw new RuntimeException("恢复定时任务失败");
        }
    }

    /**
     * 立即执行job
     *
     * @param todoJob /
     */
    public void runJobNow(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=(Scheduler) schedulers.get(statisoncode);
        try {
            TriggerKey triggerKey =
                    TriggerKey.triggerKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            Trigger trigger =
                    statisonScheduler.getTrigger(triggerKey);
            // 如果不存在则创建一个定时任务
            if (trigger == null) {
                addJob(todoJob);
            }
            JobDataMap dataMap = new JobDataMap();
            dataMap.put(TaskTodo.JOB_KEY, todoJob);
            JobKey jobKey = JobKey.jobKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
           if(DateUtil.compare(DateUtil.parse(todoJob.getPlanStartTime(),"yyyy-MM-dd HH:mm:ss"),DateUtil.date())>0){
                statisonScheduler.triggerJob(jobKey, dataMap);
            }
            } catch (Exception e) {
            log.error("定时任务执行失败", e);
            throw new RuntimeException("定时任务执行失败");
        }
    }

    /**
     * 暂停一个job
     *
     * @param todoJob /
     */
    public void pauseJob(TaskTodo todoJob) {
        String statisoncode=todoJob.getStationCode();
        Scheduler  statisonScheduler=(Scheduler) schedulers.get(statisoncode);
        try {
            JobKey jobKey = JobKey.jobKey(JOB_NAME + todoJob.getTaskTodoId(),todoJob.getStationCode());
            statisonScheduler.pauseJob(jobKey);
        } catch (Exception e) {
            log.error("定时任务暂停失败", e);
            throw new RuntimeException("定时任务暂停失败");
        }
    }


}
