using Aitex.Core.Common;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.DBCore;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.SubstrateTrackings;
using CyberX8_Core;
using CyberX8_RT.Modules;
using CyberX8_RT.Schedulers;
using SecsGem.Core.ItemModel;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.WaferHolder;

namespace CyberX8_RT.Dispatch
{
    public class JobDispatcher : ICycle
    {
        #region 内部变量
        /// <summary>
        /// 状态
        /// </summary>
        private RState _cycleState = RState.Init;
        /// <summary>
        /// Cycle计时器
        /// </summary>
        private Stopwatch _cycleWatch = new Stopwatch();
        #endregion

        /// <summary>
        /// 是否存在Job
        /// </summary>
        public bool HasJobRunning => JobProcesser.Instance.ControlJobInfos.Count > 0;
        /// <summary>
        /// 状态
        /// </summary>
        public RState CycleState => _cycleState;

        /// <summary>
        /// 构造函数
        /// </summary>
        public JobDispatcher()
        {
            SchedulerManager.Instance.Initialize();
            CycleManager.Instance.Initialize();
        }

        public void Abort()
        {
        }

        #region Job
        /// <summary>
        /// 创建任务
        /// </summary>
        /// <param name="param"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public bool CreateJob(Dictionary<string, object> param, out string reason)
        {
            return JobProcesser.Instance.CreateJob(param, out reason);
        }
        /// <summary>
        /// 暂停所有任务
        /// </summary>
        /// <returns></returns>
        public bool PauseAllJobs()
        {
            foreach(var job in JobProcesser.Instance.ControlJobInfos)
            {
                bool result = JobProcesser.Instance.PauseJob(job.Name,out string reason);
                if(!result)
                {
                    return false;
                }
            }
            _cycleState = RState.Paused;
            WaferHolderTaskManager.Instance.PauseAllTask();
            WaferTaskManager.Instance.PauseAllTask();
            return true;
        }
        /// <summary>
        /// 暂停Job
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public bool PauseJob(string jobName, out string reason)
        {
            bool result = JobProcesser.Instance.PauseJob(jobName, out reason);
            if(result)
            {
                if (!JobProcesser.Instance.ControlJobInfos.Exists(job => job.State == EnumControlJobState.Executing))
                    _cycleState = RState.Paused;
                
            }
            return result;
        }
        /// <summary>
        /// 恢复所有任务
        /// </summary>
        /// <returns></returns>
        public bool ResumeAllJobs()
        {
            foreach (var job in JobProcesser.Instance.ControlJobInfos)
            {
                bool result = JobProcesser.Instance.ResumeJob(job.Name, out string reason);
                if (!result)
                {
                    return false;
                }
            }
            WaferHolderTaskManager.Instance.ResumeAllTask();
            WaferTaskManager.Instance.ResumeAllTask();
            _cycleState = RState.Running;
            return true;
        }
        /// <summary>
        /// 恢复Job
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public bool ResumeJob(string jobName, out string reason)
        {
            bool result=JobProcesser.Instance.ResumeJob(jobName, out reason);
            if(result)
            {
                _cycleState = RState.Running;
            }
            return result;
        }
        /// <summary>
        /// 启动任务
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public bool StartJob(string jobName, out string reason)
        {
            bool result = JobProcesser.Instance.StartJob(jobName, out reason);
            if(result)
            {
                ControlJobInfo cj = JobProcesser.Instance.ControlJobInfos.Find(x => x.Name == jobName);
                if (!_cycleWatch.IsRunning)
                {
                    _cycleWatch.Restart();
                }
                List<ProcessJobInfo> pjs = JobProcesser.Instance.ProcessJobInfos;
                foreach (ProcessJobInfo item in pjs)
                {
                    foreach (var pjSlotWafer in item.SlotWafers)
                    {
                        WaferInfo wafer = WaferManager.Instance.GetWafer(pjSlotWafer.Item1, pjSlotWafer.Item2);
                        wafer.ProcessJob = item;
                        wafer.NextSequenceStep = 0;
                        WaferDataRecorder.SetPjInfo(wafer.InnerId.ToString(), item.InnerId.ToString());
                    }
                }
                _cycleState = RState.Running;
            }
            return result;
        }
        /// <summary>
        /// 停止任务
        /// </summary>
        /// <param name="jobName"></param>
        /// <param name="reason"></param>
        /// <returns></returns>
        public bool StopJob(string jobName, out string reason)
        {
            return JobProcesser.Instance.StopJob(jobName, out reason);
        }
        /// <summary>
        /// System Abort
        /// </summary>
        /// <returns></returns>
        public bool SystemAbort()
        {
            JobProcesser.Instance.SystemAbort();
            return true;
        }
        /// <summary>
        /// 删除所有job
        /// </summary>
        /// <returns></returns>
        public bool RemoveAllJob()
        {
            JobProcesser.Instance.RemoveAllJob();
            return true;
        }
        #endregion

        /// <summary>
        /// 检验是否所有任务完成
        /// </summary>
        /// <returns></returns>
        public bool CheckAllJobDone()
        {
            foreach (var cj in JobProcesser.Instance.ControlJobInfos)
            {
                if (cj.State != EnumControlJobState.Completed)
                    return false;
            }
            bool waferTask = WaferTaskManager.Instance.CheckAllTaskComplete();
            if (!waferTask)
            {
                return false;
            }
            bool waferHolderTask = WaferHolderTaskManager.Instance.CheckAllTaskComplete();
            if (!waferHolderTask)
            {
                return false;
            }
            return true;
        }
        /// <summary>
        /// 检验是否存在已经完成的任务
        /// </summary>
        /// <param name="sJobName"></param>
        /// <returns></returns>
        public bool CheckJobJustDone(out string sJobName)
        {
            foreach (var cj in JobProcesser.Instance.ControlJobInfos)
            {
                if (cj.State == EnumControlJobState.Completed && !cj.BeenPosted)
                {
                    sJobName = $"{cj.Module};{cj.JobWaferSize};{cj.LotName};{cj.LotWafers.Count};{cj.StartTime:T};{cj.EndTime:T}";
                    cj.BeenPosted = true;
                    return true;
                }
            }

            sJobName = "NULL";
            return false;
        }

        public RState CheckManualReturnWafer()
        {
            return RState.End;
        }

        public void Clear()
        {
        }
        
        public bool ManualReturnWafer(object[] objs)
        {
            return true;
        }
        /// <summary>
        /// 监控
        /// </summary>
        /// <returns></returns>
        public RState Monitor()
        {            
            UpdateProcessJobStatus();
            UpdateControlJobStatus();
            CreateWaferHolderTask();
            RunWaferHolderTask();
            RunWaferTask();
            return _cycleState;
        }

        public RState ReturnAllWafers()
        {
            return RState.Init;
        }
        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public RState Start(params object[] objs)
        {
            _cycleWatch.Stop();
            SchedulerManager.Instance.ResetSchedulerModule();
            CycleManager.Instance.InitializeAllLoadPortData();
            return RState.Running;
        }
        /// <summary>
        /// 更新ProcessJob状态
        /// </summary>
        private void UpdateProcessJobStatus()
        {
            foreach (var pj in JobProcesser.Instance.ProcessJobInfos)
            {
                if (CheckAllWaferReturned(pj, pj.State != EnumProcessJobState.Stopping))
                {
                    pj.SetState(EnumProcessJobState.ProcessingComplete);
                    JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
                    JobProcesser.Instance.RemoveRecipeProcessJob(pj);
                }
            }

            List<ProcessJobInfo> list = JobProcesser.Instance.GetRecipeStateProcessJobs(EnumProcessJobState.Queued);
            foreach(var item in list)
            {
                if(SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(item.SequenceRecipe, false))
                {
                    ActiveProcessJob(item);
                }
                else
                {
                    UpdateProcessJobCanceled(item);
                }
            }
        }
        /// <summary>
        /// ProcessJob状态修改为canceled
        /// </summary>
        /// <param name="pj"></param>
        private void UpdateProcessJobCanceled (ProcessJobInfo pj)
        {
            foreach (var slot in pj.SlotWafers)
            {
                var wafer = WaferManager.Instance.GetWafer(slot.Item1, slot.Item2);
                if (!wafer.IsEmpty&&wafer.ProcessState==EnumWaferProcessStatus.Idle)
                {
                    wafer.ProcessState = EnumWaferProcessStatus.Canceled;
                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"wafer {slot.Item1} slot {slot.Item2} state changed to canceled");
                }
            }
            pj.SetState(EnumProcessJobState.Canceled);
            JobDataRecorder.EndPJ(pj.InnerId.ToString(), 0, 0);
            LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"Processjob sequence {pj.SequenceRecipe.Ppid} not avaible cell,state changed to canceled");
        }
        /// <summary>
        /// 检验ProcessJob是否所有Wafer已经回到了LoadPort
        /// </summary>
        /// <param name="pj"></param>
        /// <param name="checkAllProcessed"></param>
        /// <returns></returns>
        private bool CheckAllWaferReturned(ProcessJobInfo pj, bool checkAllProcessed)
        {
            bool allWaferReturn = true;
            foreach (var slot in pj.SlotWafers)
            {
                var wafer = WaferManager.Instance.GetWafer(slot.Item1, slot.Item2);
                if (wafer.IsEmpty || (wafer.ProcessState != EnumWaferProcessStatus.Completed && checkAllProcessed))
                {
                    allWaferReturn = false;
                    break;
                }
            }

            return allWaferReturn;
        }
        /// <summary>
        /// 更新ControlJob状态
        /// </summary>
        private void UpdateControlJobStatus()
        {
            if(JobProcesser.Instance.ControlJobInfos==null||JobProcesser.Instance.ControlJobInfos.Count==0)
            {
                return;
            }
            List<ControlJobInfo> runningJobs=JobProcesser.Instance.getRunningControlJobs();
            foreach (ControlJobInfo controlJobInfo in runningJobs)
            {
                if (IsAllProcessJobComplete(controlJobInfo))
                {
                    CycleManager.Instance.UpdateCycleCount(controlJobInfo.Module);
                    if (CycleManager.Instance.GetLoadportCycleCount(controlJobInfo.Module) >= controlJobInfo.CycleNumber)
                    {
                        JobProcesser.Instance.CompleteControlJob(controlJobInfo);
                        FaJobManager.Instance.Complete(controlJobInfo.Name);
                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{controlJobInfo.Name} complete");
                    }
                    else
                    {
                        JobProcesser.Instance.RestartControlJob(controlJobInfo);
                    }
                }
            }
            if(CheckAllJobDone())
            {
                _cycleState = RState.End;
            }
        }
        /// <summary>
        /// 是否所有ProcessJob已经完成
        /// </summary>
        /// <param name="cj"></param>
        /// <returns></returns>
        private bool IsAllProcessJobComplete(ControlJobInfo cj)
        {
            foreach (var pj in JobProcesser.Instance.ProcessJobInfos)
            {
                if (pj.ControlJobName == cj.Name)
                {
                    if (pj.State == EnumProcessJobState.Canceled)
                    {
                        if (!CheckAllWaferReturned(pj, false))
                        {
                            return false;
                        }
                    }
                    else if (pj.State != EnumProcessJobState.ProcessingComplete)
                    {
                        return false;
                    }
                }

                
                for (int i = 0; i < pj.SlotWafers.Count; i++)
                {
                    var item = pj.SlotWafers[i];
                    if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2))
                    {
                        WaferInfo waferInfo = WaferManager.Instance.GetWafer(item.Item1, item.Item2);
                        if(WaferTaskManager.Instance.Contains(waferInfo.WaferID))
                        {
                            return false;
                        }
                    }
                }
            }

            return true;
        }
        /// <summary>
        /// 启动ProcessJob
        /// </summary>
        /// <param name="pj"></param>
        /// <returns></returns>
        private bool ActiveProcessJob(ProcessJobInfo pj)
        {
            if (pj.State == EnumProcessJobState.Queued)
            {
                ControlJobInfo cj = JobProcesser.Instance.ControlJobInfos.Find(O => O.Name == pj.ControlJobName);
                if (cj == null)
                {
                    return false;
                }
                CarrierInfo carrier = CarrierManager.Instance.GetCarrier(cj.Module);
                JobDataRecorder.StartPJ(pj.InnerId.ToString(), carrier.InnerId.ToString(), cj.InnerId.ToString(), pj.Name, cj.Module, cj.Module, pj.SlotWafers.Count);

                pj.SetState(EnumProcessJobState.Processing);
            }
            return true;
        }
        /// <summary>
        /// 创建WaferHolder任务
        /// </summary>
        private void CreateWaferHolderTask()
        {
            if (JobProcesser.Instance.ProcessJobInfos.Count == 0) { return; }
            //查看Loader之前是否有Wafer(出现场景LoaderTransporter取WaferHolder出现Id不匹配,Loader前面就已经存在了Wafer)
            WaferInfo waferInfo = WaferHolderTaskManager.Instance.GetPreLoaderHasWafer();
            List<ProcessJobInfo> tmpProcessJobs = new List<ProcessJobInfo>();
            if (waferInfo == null)
            {
                var runningProcessJobs = JobProcesser.Instance.GetRecipeStateProcessJobs(EnumProcessJobState.Processing);
                foreach (var job in runningProcessJobs)
                {
                    if (!SchedulerSequenceRecipeManager.Instance.ExistAvaibleProcessCell(job.SequenceRecipe, false))
                    {
                        UpdateProcessJobCanceled(job);
                        continue;
                    }
                    if (!CheckProcessJobHasUncompleteWafer(job))
                    {
                        continue;
                    }
                    List<string> chemistries = SchedulerSequenceRecipeManager.Instance.GetSequenceChemistry(job.SequenceRecipe);
                    WaferSize waferSize = (WaferSize)job.SequenceRecipe.SubstrateSize;
                    WaferHolderInfo waferHolderInfo = SchedulerManager.Instance.GetAvaibleBufferToLoaderWaferHolder(waferSize, job.SequenceRecipe.CrsType, chemistries);
                    if (waferHolderInfo == null)
                    {
                        continue;
                    }
                    tmpProcessJobs.Add(job);
                    break;
                }
            }
            else
            {
                if (waferInfo.ProcessJob != null)
                {
                    tmpProcessJobs.Add(waferInfo.ProcessJob);
                }
            }
            if (tmpProcessJobs.Count != 0)
            {
                WaferHolderTaskManager.Instance.CreateWaferHolderTask(tmpProcessJobs);
            }
            else
            { 
                WaferHolderTaskManager.Instance.CreateDummyWaferHolderTask();
            }
        }

        /// <summary>
        /// 检验ProcessJob是否存在未加工的Wafer
        /// </summary>
        /// <param name="pj"></param>
        /// <returns></returns>
        private bool CheckProcessJobHasUncompleteWafer(ProcessJobInfo pj)
        {
            for (int i = 0; i < pj.SlotWafers.Count; i++)
            {
                var item = pj.SlotWafers[i];
                if (WaferManager.Instance.CheckHasWafer(item.Item1, item.Item2))
                {
                    WaferInfo waferInfo = WaferManager.Instance.GetWafer(item.Item1, item.Item2);
                    if (waferInfo != null && waferInfo.ProcessState == EnumWaferProcessStatus.Idle)
                    {
                        if (!WaferTaskManager.Instance.Contains(waferInfo.WaferID))
                        {
                            return true;
                        }
                    }
                }
            }
            return false;
        }

        /// <summary>
        /// 运行WaferHolder任务
        /// </summary>
        private void RunWaferHolderTask()
        {
            WaferHolderTaskDispatcher.Instance.Analyse();
        }
        /// <summary>
        /// 运行Wafer任务
        /// </summary>
        private void RunWaferTask()
        {
            List<WaferTask> waferTasks = WaferTaskManager.Instance.LoadWaferTaskList();
            foreach(var item in waferTasks)
            {
                item.Run();
            }
        }       
    }
}