
using Quartz;
using Quartz.Impl;
using Quartz.Impl.Triggers;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Linq;
using System.Text;

namespace CallCenter.QuartzService
{
    public class QuartzWorker
    {
        public Log log = LogFactory.GetLogger("定时");
        public QuartzWorker()
        {

        }
        /// <summary>
        /// 初始化IScheduler
        /// </summary>
        /// <returns></returns>
        public IScheduler GetScheduler()
        {
            IScheduler _scheduler = null;
            try
            {
                var properties = new NameValueCollection();
                //properties["quartz.scheduler.instanceName"] = "RemoteServerSchedulerClient";
                // 设置线程池
                properties["quartz.threadPool.type"] = "Quartz.Simpl.SimpleThreadPool, Quartz";
                properties["quartz.threadPool.threadCount"] = "10";
                properties["quartz.threadPool.threadPriority"] = "Normal";

                // 远程输出配置
                properties["quartz.scheduler.exporter.type"] = "Quartz.Simpl.RemotingSchedulerExporter, Quartz";
                properties["quartz.scheduler.exporter.port"] = "556";
                properties["quartz.scheduler.exporter.bindName"] = "QuartzScheduler";
                properties["quartz.scheduler.exporter.channelType"] = "tcp";

                var schedulerFactory = new StdSchedulerFactory(properties);
                _scheduler = schedulerFactory.GetScheduler();
            }
            catch (Exception ex)
            {
                log.Info("QuartzWorker初始化失败，失败原因：" + ex.ToString());
            }

            return _scheduler;
        }

        /// <summary>
        /// 添加一个任务
        /// </summary>
        /// <param name="job"></param>
        public bool AddWork(QuartzJob job, IScheduler _scheduler)
        {
            var type = job.GetType();
            var jobName = "job_" + job.jobID;
            var jobGroup = "group_" + job.jobID;

            bool bl = false;
            try
            {
                JobKey jk = new JobKey(jobName, jobGroup);
                if (_scheduler.GetJobDetail(jk) == null)
                {
                    // 创建一个工作
                    var jobDetail = new JobDetailImpl(jobName, jobGroup, type, true, true);
                    // 创建一个触发器
                    Quartz.Collection.HashSet<ITrigger> triggerSet = new Quartz.Collection.HashSet<ITrigger>();
                    var cronExpressionList = job.CronExpressionList;
                    for (int i = 0; i < cronExpressionList.Count; i++)
                    {
                        var triggerName = "trigger_" + job.jobID + "_" + (i + 1);
                        //触发器名称必须不同，否则最终只会添加一个触发器
                        triggerSet.Add(new CronTriggerImpl(triggerName, jobGroup, jobName, jobGroup, cronExpressionList[i]));

                        log.Info(triggerName + "已新增，规则：" + cronExpressionList[i]);
                    }
                    _scheduler.ScheduleJob(jobDetail, triggerSet, false);

                    //启动任务
                    if (!_scheduler.IsStarted)
                    {
                        Start(_scheduler);
                    }
                    else
                    {
                        _scheduler.ResumeJob(jk);
                    }
                    log.Info("启动任务：" + jobName);
                }
                else
                {
                    Update(job, _scheduler);
                }

                bl = true;
            }
            catch (Exception ex)
            {
                log.Info("添加任务失败，失败原因：" + ex.ToString());
            }

            return bl;
        }

        /// <summary>
        /// 开始运行
        /// </summary>
        public void Start(IScheduler _scheduler)
        {
            _scheduler.Start();
            log.Info("QuartzWorker已启动");
        }

        /// <summary>
        /// 停止运行
        /// </summary>
        public void Stop(IScheduler _scheduler)
        {
            _scheduler.Shutdown(true);
            log.Info("QuartzWorker已停止");

        }

        /// <summary>
        /// 暂停所有定时任务
        /// </summary>
        public void PauseAll(IScheduler _scheduler)
        {
            _scheduler.PauseAll();
            log.Info("暂停所有定时任务");
        }

        /// <summary>
        /// 重新启动所有定时任务
        /// </summary>
        public void ResumeAll(IScheduler _scheduler)
        {
            _scheduler.ResumeAll();
            log.Info("重新启动所有定时任务");
        }

        /// <summary>
        /// 修改任务触发器
        /// </summary>
        public void Update(QuartzJob job, IScheduler _scheduler)
        {
            var jobName = "job_" + job.jobID;
            var jobGroup = "group_" + job.jobID;

            try
            {
                var cronExpressionList = job.CronExpressionList;
                JobKey jk = new JobKey(jobName, jobGroup);
                List<ITrigger> list = _scheduler.GetTriggersOfJob(jk).ToList();
                for (int i = 0; i < list.Count; i++)
                {

                    TriggerKey tk = list[i].Key;
                    _scheduler.PauseTrigger(tk);
                    _scheduler.UnscheduleJob(tk);

                }

                Quartz.Collection.HashSet<ITrigger> triggerSet = new Quartz.Collection.HashSet<ITrigger>();
                for (int i = 0; i < cronExpressionList.Count; i++)
                {
                    var triggerName = "trigger_" + job.jobID + "_" + (i + 1);

                    var trigger = new CronTriggerImpl(triggerName, jobGroup, jobName, jobGroup, cronExpressionList[i]);

                    triggerSet.Add(trigger);

                    log.Info(triggerName + "已修改，规则：" + cronExpressionList[i]);
                }

                _scheduler.ScheduleJob(_scheduler.GetJobDetail(jk), triggerSet, true);
            }
            catch (Exception ex)
            {
                log.Info(jobName + "修改失败，原因：" + ex.ToString());
            }
        }

        /// <summary>
        /// 移除任务
        /// </summary>
        public void Delete(QuartzJob job, IScheduler _scheduler)
        {
            var jobName = "job_" + job.jobID;
            var jobGroup = "group_" + job.jobID;

            try
            {
                JobKey jk = new JobKey(jobName, jobGroup);

                foreach (var tri in _scheduler.GetTriggersOfJob(jk))
                {
                    _scheduler.PauseTrigger(tri.Key);
                    _scheduler.UnscheduleJob(tri.Key);
                }

                _scheduler.DeleteJob(jk);

                log.Info(jobName + "已移除");
            }
            catch (Exception ex)
            {
                log.Info(jobName + "移除失败，原因：" + ex.ToString());
            }
        }
    }
}
