package com.ssm.config;

import com.ssm.task.*;
import org.quartz.Trigger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.PropertySource;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.quartz.CronTriggerFactoryBean;
import org.springframework.scheduling.quartz.JobDetailFactoryBean;
import org.springframework.scheduling.quartz.SchedulerFactoryBean;

import java.io.IOException;
import java.util.Properties;

@Configuration
@PropertySource(value = "classpath:config/quartz.properties")
@EnableScheduling
public class QuartzConfig {
    @Autowired
    private MyJobFactory myJobFactory;
    @Value("${org.quartz.scheduler.instanceName}")
    private String quartzInstanceName;

    @Value("${org.quartz.scheduler.instanceId}")
    private String instanceId;

    @Value("${org.quartz.threadPool.threadCount}")
    private String threadCount;

    @Value("${org.quartz.threadPool.class}")
    private String threadPool;

    @Value("${org.quartz.threadPool.threadPriority}")
    private String threadPriority;

    @Value("${org.quartz.jobStore.misfireThreshold}")
    private String misfireThreshold;

    @Value("${org.quartz.jobStore.class}")
    private String jobStoreClass;

    @Value("${org.quartz.dataSource.quartzDS.driver}")
    private String quartzDSDriver;

    @Value("${org.quartz.dataSource.quartzDS.URL}")
    private String quartzDSURL;

    @Value("${org.quartz.dataSource.quartzDS.user}")
    private String quartzDSUser;

    @Value("${org.quartz.dataSource.quartzDS.password}")
    private String quartzDSPassword;

    @Value("${org.quartz.dataSource.quartzDS.maxConnections}")
    private String quartzDSMaxConnections;

    @Value("${org.quartz.jobStore.isClustered}")
    private String isClustered;

    @Value("${org.quartz.jobStore.clusterCheckInInterval}")
    private String clusterCheckInInterval;

    @Value("${quartz.trigger.cronDayCreateTable}")
    private String cronDayCreateTable;

    @Value("${quartz.trigger.cronCallNum}")
    private String cronCallNum;

    @Value("${quartz.trigger.cronNegativeCard}")
    private String cronNegativeCard;

    @Value("${quartz.trigger.cronDayStopMember}")
    private String cronDayStopMember;

    private Properties quartzProperties() throws IOException {
        Properties prop = new Properties();
        prop.put("quartz.scheduler.instanceName", quartzInstanceName);
        prop.put("org.quartz.scheduler.instanceId", instanceId);
        prop.put("org.quartz.scheduler.skipUpdateCheck", "true");
        prop.put("org.quartz.scheduler.jmx.export", "true");

        prop.put("org.quartz.jobStore.class", jobStoreClass);
        prop.put("org.quartz.jobStore.driverDelegateClass", "org.quartz.impl.jdbcjobstore.StdJDBCDelegate");
        prop.put("org.quartz.jobStore.dataSource", "quartzDataSource");
        prop.put("org.quartz.jobStore.tablePrefix", "QRTZ_");
        prop.put("org.quartz.jobStore.isClustered", isClustered);

        prop.put("org.quartz.jobStore.clusterCheckinInterval", clusterCheckInInterval);
        prop.put("org.quartz.jobStore.dataSource", "quartzDS");
        prop.put("org.quartz.jobStore.maxMisfiresToHandleAtATime", "1");
        prop.put("org.quartz.jobStore.misfireThreshold", misfireThreshold);
        prop.put("org.quartz.jobStore.txIsolationLevelSerializable", "true");
        prop.put("org.quartz.jobStore.selectWithLockSQL", "SELECT * FROM {0}LOCKS WHERE LOCK_NAME = ? FOR UPDATE");

        prop.put("org.quartz.threadPool.class", threadPool);
        prop.put("org.quartz.threadPool.threadCount", threadCount);
        prop.put("org.quartz.threadPool.threadPriority", threadPriority);
        prop.put("org.quartz.threadPool.threadsInheritContextClassLoaderOfInitializingThread", "true");

        prop.put("org.quartz.dataSource.quartzDS.driver", quartzDSDriver);
        prop.put("org.quartz.dataSource.quartzDS.URL", quartzDSURL);
        prop.put("org.quartz.dataSource.quartzDS.user", quartzDSUser);
        prop.put("org.quartz.dataSource.quartzDS.password", quartzDSPassword);
        prop.put("org.quartz.dataSource.quartzDS.maxConnections", quartzDSMaxConnections);

        prop.put("org.quartz.plugin.triggHistory.class", "org.quartz.plugins.history.LoggingJobHistoryPlugin");
        prop.put("org.quartz.plugin.shutdownhook.class", "org.quartz.plugins.management.ShutdownHookPlugin");
        prop.put("org.quartz.plugin.shutdownhook.cleanShutdown", "true");
        return prop;
    }



    private static JobDetailFactoryBean createJobDetail(Class jobClass) {
        JobDetailFactoryBean factoryBean = new JobDetailFactoryBean();
        factoryBean.setJobClass(jobClass);
        factoryBean.setDurability(true);

        return factoryBean;
    }

    /**
     * attention:
     * Details：定义quartz调度工厂
     */
    @Bean(name = "scheduler2")
    public SchedulerFactoryBean schedulerFactory(@Qualifier("dayCreateTableTrigger")Trigger dayCreateTableTrigger,@Qualifier("callNumTrigger")Trigger callNumTrigger,
                                                 @Qualifier("negativeCardTrigger")Trigger negativeCardTrigger,@Qualifier("dayStopMemberTrigger")Trigger dayStopMemberTrigger
    ) throws IOException {
        SchedulerFactoryBean bean = new SchedulerFactoryBean();
        bean.setJobFactory(myJobFactory);
        // 用于quartz集群,QuartzScheduler 启动时更新己存在的Job
        bean.setOverwriteExistingJobs(true);
        //用于quartz集群,加载quartz数据源
        //bean.setDataSource(dataSource);
        //QuartzScheduler 延时启动，应用启动完10秒后 QuartzScheduler 再启动
        bean.setStartupDelay(10);
        //用于quartz集群,加载quartz数据源配置
        bean.setQuartzProperties(quartzProperties());
        bean.setAutoStartup(true);
        bean.setApplicationContextSchedulerContextKey("applicationContext");
        // 注册触发器
        bean.setTriggers(dayCreateTableTrigger,callNumTrigger,negativeCardTrigger,dayStopMemberTrigger);
        return bean;
    }


    @Bean(name = "dayCreateTableDetail")
    public JobDetailFactoryBean dayCreateTableDetail(){
        JobDetailFactoryBean jobDetailFactoryBean = createJobDetail(SsmDayCreateTableTask.class);
        jobDetailFactoryBean.setGroup("dayCreateTableDetailGroup");
        return jobDetailFactoryBean;
    }

    @Bean(name = "dayCreateTableTrigger")
    public CronTriggerFactoryBean dayCreateTableTrigger(@Qualifier("dayCreateTableDetail") JobDetailFactoryBean dayCreateTableDetail){
        CronTriggerFactoryBean trigger=new CronTriggerFactoryBean();
        trigger.setJobDetail(dayCreateTableDetail.getObject());
        trigger.setCronExpression(cronDayCreateTable);
        trigger.setName("dayCreateTableTrigger");
        return trigger;
    }

    @Bean(name = "callNumDetail")
    public JobDetailFactoryBean callNumDetail(){
        JobDetailFactoryBean jobDetailFactoryBean = createJobDetail(SsmCallNumTask.class);
        jobDetailFactoryBean.setGroup("callNumDetailGroup");
        return jobDetailFactoryBean;
    }

    @Bean(name = "callNumTrigger")
    public CronTriggerFactoryBean callNumTrigger(@Qualifier("callNumDetail") JobDetailFactoryBean callNumDetail){
        CronTriggerFactoryBean trigger=new CronTriggerFactoryBean();
        trigger.setJobDetail(callNumDetail.getObject());
        trigger.setCronExpression(cronCallNum);
        trigger.setName("callNumTrigger");
        return trigger;
    }

    @Bean(name = "negativeCardDetail")
    public JobDetailFactoryBean negativeCardDetail(){
        JobDetailFactoryBean jobDetailFactoryBean = createJobDetail(SsmNegativeCardTask.class);
        jobDetailFactoryBean.setGroup("negativeCardDetailGroup");
        return jobDetailFactoryBean;
    }

    @Bean(name = "negativeCardTrigger")
    public CronTriggerFactoryBean negativeCardTrigger(@Qualifier("negativeCardDetail") JobDetailFactoryBean negativeCardDetail){
        CronTriggerFactoryBean trigger=new CronTriggerFactoryBean();
        trigger.setJobDetail(negativeCardDetail.getObject());
        trigger.setCronExpression(cronNegativeCard);
        trigger.setName("negativeCardTrigger");
        return trigger;
    }

    @Bean(name = "dayStopMemberDetail")
    public JobDetailFactoryBean dayStopMemberDetail(){
        JobDetailFactoryBean jobDetailFactoryBean = createJobDetail(SsmDayStopMemberTask.class);
        jobDetailFactoryBean.setGroup("dayStopMemberDetailGroup");
        return jobDetailFactoryBean;
    }

    @Bean(name = "dayStopMemberTrigger")
    public CronTriggerFactoryBean dayStopMemberTrigger(@Qualifier("dayStopMemberDetail") JobDetailFactoryBean dayStopMemberDetail){
        CronTriggerFactoryBean trigger=new CronTriggerFactoryBean();
        trigger.setJobDetail(dayStopMemberDetail.getObject());
        trigger.setCronExpression(cronDayStopMember);
        trigger.setName("dayStopMemberTrigger");
        return trigger;
    }

}
