using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Quartz;
using Quartz.Impl;
using PushInfo.Core.BLL;
using PushInfo.Core.Models.Tables;
using PushPlatform.Common.Util;
using PushInfo.Core.Models.QueryResults;
using PushPlatform.Common.Enumerate;

namespace PushInfo.Core.Quartz.Jobs
{
    /// <summary>
    /// 加载推送任务
    /// </summary>
    public class LoadPushJob : IJob
    {
        static ISchedulerFactory _sf = new StdSchedulerFactory();

        static IScheduler _sched = _sf.GetScheduler("ExampleDefaultQuartzScheduler");

        MapProjectPushBLL mProPushBll = new MapProjectPushBLL();

        public string Group
        {
            get
            {
                return "pushJob";
            }
        }
        public void Execute(IJobExecutionContext context)
        {
            try
            {
                List<Map_Project_Push> taskList = mProPushBll.GetStandByTask();
                if (taskList != null && taskList.Count > 0)
                {
                    LogHelper.Debug("加载任务");
                    foreach (Map_Project_Push item in taskList)
                    {
                        JobKey jobKey = new JobKey(item.Id.ToString(), Group);
                        LogHelper.Debug("jobKey：" + jobKey);
                        var jobDetail = _sched.GetJobDetail(jobKey);
                        if (jobDetail != null)
                        {
                            LogHelper.Debug("jobDetail不是NULL，jobKey.NAME：" + jobDetail.Key.Name);
                        }

                        //当任务状态不是 需要移除的，可以重新加载
                        if (jobDetail == null && item.Exec_Status == Convert.ToInt32(ExecuteStatus.新建未安排触发器))
                        {
                            LogHelper.Debug("jobDetail是NULL,创建任务");
                            CreateTask(item);
                        }
                        else if (jobDetail != null)
                        {
                            //当任务状态不是已经移除的，可以进行修改 
                            LogHelper.Debug("jobDetail 不是NULL，执行状态：" + item.Exec_Status);
                            if (item.Exec_Status == Convert.ToInt32(ExecuteStatus.修改后未安排触发器))
                            {
                                LogHelper.Debug("修改任务");
                                bool modifyResult = ModifyTask(item);
                                LogHelper.Debug("结果：" + modifyResult);
                            }
                            else if (item.Exec_Status == Convert.ToInt32(ExecuteStatus.等待从触发器中移除))
                            {
                                LogHelper.Debug("jobDetail不是NULL,移除任务");
                                bool removeResult = RemoveTask(item, ExecuteStatus.已经停用);
                                LogHelper.Debug("结果：" + removeResult);
                            }
                        }
                        else if (jobDetail == null && item.Exec_Status == Convert.ToInt32(ExecuteStatus.修改后未安排触发器))
                        {
                            LogHelper.Debug("jobDetail是NULL,重新安排，重新创建任务");
                            CreateTask(item);
                        }

                        LogHelper.Debug("-------------------------------------------------------------------");
                    }
                }

                if (!_sched.IsStarted)
                    _sched.Start();
            }
            catch (Exception e)
            {
                LogHelper.Error(e);
            }
        }

        #region 添加任务
        /// <summary>
        /// 添加任务
        /// </summary>
        /// <param name="task">配置任务记录</param>
        /// <returns></returns>
        public bool CreateTask(Map_Project_Push task)
        {
            LogHelper.Debug("添加任务" + task.Name_Des);
            try
            {
                if (task == null)
                    return false;

                JobKey key = new JobKey(task.Id.ToString(), Group);

                var job = _sched.GetJobDetail(key);

                if (job != null)
                    return false;
                else
                {
                    job = JobBuilder.Create<PushJob>()
                        .WithIdentity(task.Id.ToString(), Group)
                        .WithDescription(task.Name_Des)
                        .Build();
                    ITrigger trigger = SetTrigger(task);
                    _sched.ScheduleJob(job, trigger);
                    return true;
                }
            }
            catch (Exception e)
            {
                LogHelper.Error(e);
                return false;
            }
        }
        #endregion

        #region 删除任务
        public bool RemoveTask(Map_Project_Push task, ExecuteStatus exeStatus)
        {
            LogHelper.Debug("删除任务" + task.Name_Des);
            try
            {
                if (task == null)
                    return false;

                JobKey key = new JobKey(task.Id.ToString(), Group);

                var job = _sched.GetJobDetail(key);
                if (job == null)
                {
                    mProPushBll.Modify_Task_Excute(task.Id, exeStatus);
                    return true;
                }
                else
                {
                    mProPushBll.Modify_Task_Excute(task.Id, exeStatus);
                    return _sched.DeleteJob(key);
                }
            }
            catch (Exception e)
            {
                LogHelper.Error(e);
                return false;
            }
        }
        #endregion

        #region 修改任务
        public bool ModifyTask(Map_Project_Push task)
        {
            try
            {
                LogHelper.Debug("修改任务" + task.Name_Des);
                if (task == null)
                    return false;

                JobKey key = new JobKey(task.Id.ToString(), Group);

                var job = _sched.GetJobDetail(key);

                if (job == null)
                    return false;

                var triggerKey = new TriggerKey(task.Trigger_Key.ToString(), Group);
                var trigger = _sched.GetTrigger(triggerKey);
                if (trigger == null)
                    return false;

                _sched.RescheduleJob(triggerKey, SetTrigger(task));
                return true;
            }
            catch(Exception ex)
            {
                LogHelper.Error(ex);
                return false;
            }
            
        }
        #endregion

        #region 根据任务设置trigger
        /// <summary>
        /// 根据任务设置trigger
        /// </summary>
        /// <param name="task">任务实体</param>
        /// <returns></returns>
        private ITrigger SetTrigger(Map_Project_Push task)
        {
            try
            {
                if (task != null)
                {
                    //任务的触发器名称
                    string triggerKey = Guid.NewGuid().ToString();
                    //ISimpleTrigger trigger;
                    ITrigger trigger;
                    //定义任务开始时间,需要转为本地时间
                    DateTimeOffset startTime;
                    //如果任务时间早于当前时间，将启动时间设置为当前时间
                    if (task.Exec_Time.CompareTo(DateTime.Now) <= 0)
                        startTime = DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local);
                    else
                        startTime = DateTime.SpecifyKind(task.Exec_Time, DateTimeKind.Local);

                    ResultHelper<string> rs = mProPushBll.Modify_Task_Excute(task.Id, ExecuteStatus.已安排触发器, triggerKey);
                    if (rs.result == 0)
                    {
                        return null;
                    }
                    if (rs.result == 1)
                    {
                        int minute = startTime.Minute;
                        int hous = startTime.Hour;
                        if (task.Push_Type == (int)PushType.小时)
                        {
                            //间隔时间为小时
                            trigger = TriggerBuilder.Create()
                                .WithIdentity(rs.data.ToString(), Group)
                                .WithSimpleSchedule(x => x.WithIntervalInHours(task.Push_Cycle ?? 0).RepeatForever())
                                .StartAt(startTime)
                                .Build();
                            LogHelper.Debug("设置任务【" + task.Name_Des + "】，周期类型【小时】，执行周期：【" + (task.Push_Cycle ?? 0) + "】");
                        }
                        else if (task.Push_Type == (int)PushType.天)
                        {
                            //间隔时间为天 每天的  HH:MM:SS 执行
                            trigger = TriggerBuilder.Create()
                                .WithIdentity(rs.data.ToString(), Group)
                                .WithSimpleSchedule(x => x.WithIntervalInHours(24*(task.Push_Cycle ?? 1)).RepeatForever())
                                .StartAt(startTime)
                                .Build();
                            LogHelper.Debug("设置任务【" + task.Name_Des + "】，周期类型【天】，执行周期：【" + (task.Push_Cycle ?? 1) + "】");
                        }
                        else if(task.Push_Type == (int)PushType.周)  //没有实现隔多少周
                        {
                            if(string.IsNullOrEmpty(task.Push_Which))
                            {
                                task.Push_Which = (Convert.ToInt32(task.Exec_Time.DayOfWeek)+1).ToString();
                            }
                            else
                            {
                                task.Push_Which.Trim();
                            }
                            string cron = string.Format("{0} {1} {2} {3} {4} {5}","59", minute.ToString(), hous.ToString(), "?", "*", task.Push_Which);
                            
                            trigger = TriggerBuilder.Create()
                                .WithIdentity(rs.data.ToString(), Group)
                                .WithCronSchedule(cron)
                                .StartAt(startTime)
                                .Build();
                            LogHelper.Debug("设置任务【" + task.Name_Des + "】，周期类型【周】，执行周：【" + task.Push_Which + "】");
                        }
                        else if(task.Push_Type == (int)PushType.月)
                        {
                            if (string.IsNullOrEmpty(task.Push_Which))
                            {
                                task.Push_Which = task.Exec_Time.Day.ToString();
                            }
                            else
                            {
                                task.Push_Which.Trim();
                                if (task.Push_Which.IndexOf("32") > -1)  //判断是否要每月的最后一天
                                {
                                    task.Push_Which = task.Push_Which.Replace("32", "L");
                                }
                            }
                            if(string.IsNullOrEmpty(task.Push_Month))
                            {
                                task.Push_Month = "*";
                            }
                            string cron = string.Format("{0} {1} {2} {3} {4} {5}", "59", minute.ToString(), hous.ToString(), task.Push_Which, task.Push_Month, "?");
                            
                            trigger = TriggerBuilder.Create()
                                .WithIdentity(rs.data.ToString(), Group)
                                .WithCronSchedule(cron)
                                .StartAt(startTime)
                                .Build();
                            LogHelper.Debug("设置任务【" + task.Name_Des + "】，周期类型【月】，执行周期：【" + task.Push_Cycle + "】");
                        }
                        else
                        {
                            //一次性执行的任务
                            trigger = TriggerBuilder.Create()
                                .WithIdentity(rs.data.ToString(), Group)
                                .WithSimpleSchedule(x => x.WithRepeatCount(0))
                                .StartAt(startTime).Build();
                            LogHelper.Debug("设置任务【" + task.Name_Des + "】，周期类型一次执行");
                        }
                        return trigger;
                    }
                    else
                    {
                        return null;
                    }
                }
                else
                    return null;
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex);
            }
            return null;
        }
        #endregion
    }
}
