using Aitex.Core.Common;
using Aitex.Core.RT.IOCore;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Jobs;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.Common.WaferHolder;
using CyberX8_Core;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Loader;
using CyberX8_RT.Modules.PUF;
using CyberX8_RT.Schedulers;
using CyberX8_RT.Schedulers.EfemRobot;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Schedulers;
using System.Windows;
using MECF.Framework.RT.Core.Equipments;
using CyberX8_RT.Modules.SRD;
using CyberX8_RT.Schedulers.Puf;

namespace CyberX8_RT.Dispatch
{
    public enum WaferTaskState
    {
        Created,
        Processing,
        End,
        Paused,
        Error
    }

    /// <summary>
    /// WaferTask完成
    /// </summary>
    /// <param name="id"></param>
    public delegate void WaferTaskComplete(string id);
    /// <summary>
    /// WaferTask开始
    /// </summary>
    /// <param name="id"></param>
    public delegate void WaferTaskStart(string id);
    public class WaferTask
    {
        #region 内部变量
        /// <summary>
        /// 调度步骤
        /// </summary>
        private List<SchedulerSequence> _schedulerSequences;
        /// <summary>
        /// 当前步骤索引
        /// </summary>
        private int _currentSequenceIndex = 0;
        /// <summary>
        /// PUF实例
        /// </summary>
        private PUFEntity _pufEntity;
        /// <summary>
        /// 是否开始执行
        /// </summary>
        private bool _isStart = false;
        /// <summary>
        /// 暂停时的索引
        /// </summary>
        private int _pausedIndex = -1;
        /// <summary>
        /// 日志trigger
        /// </summary>
        private R_TRIG _sequenceConditionTrigger = new R_TRIG();
        /// <summary>
        /// 错误上升触发
        /// </summary>
        private R_TRIG _sequenceErrorTigger = new R_TRIG();
        #endregion

        #region 属性
        /// <summary>
        /// Wafer信息
        /// </summary>
        public string WaferId { get; set; }
        /// <summary>
        /// 状态
        /// </summary>
        public WaferTaskState State { get; private set; }
        /// <summary>
        /// 匹配WaferTask
        /// </summary>
        public string MateWaferTask { get; set; }
        /// <summary>
        /// 调度集合
        /// </summary>
        public List<SchedulerSequence> SchedulerSequences { get { return _schedulerSequences; } }
        #endregion

        #region 事件
        /// <summary>
        /// 任务完成事件
        /// </summary>
        public event WaferTaskComplete OnTaskComplete;
        /// <summary>
        /// 任务启动
        /// </summary>
        public event WaferTaskStart OnTaskStart;
        #endregion
        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="waferInfo"></param>
        /// <param name="schedulerSequences"></param>
        public WaferTask(WaferInfo waferInfo,PUFEntity pufEntity, List<SchedulerSequence> schedulerSequences)
        {
            this.WaferId = waferInfo.WaferID;
            _schedulerSequences = schedulerSequences;
            State = WaferTaskState.Created;
            _pufEntity = pufEntity;
        }
        /// <summary>
        /// 执行
        /// </summary>
        public void Run()
        {
            if (State == WaferTaskState.Error)
            {
                return;
            }
            if (_currentSequenceIndex >= _schedulerSequences.Count)
            {
                State = WaferTaskState.End;
                if (OnTaskComplete != null)
                {
                    OnTaskComplete(WaferId);
                }
                WaferTaskManager.Instance.RemoveWaferIdMatchWaferHolderTaskDic(WaferId);
                return;
            }
            SchedulerSequence sequence = _schedulerSequences[_currentSequenceIndex];
            if (_currentSequenceIndex == _schedulerSequences.Count - 1 && sequence.State == RState.End)
            {
                State = WaferTaskState.End;
                if(OnTaskComplete!=null)
                {
                    OnTaskComplete(WaferId);
                }
                WaferTaskManager.Instance.RemoveWaferIdMatchWaferHolderTaskDic(WaferId);
                return;
            }
            if (!_isStart)
            {
                bool preCondition = CheckStartCondition();
                if (!preCondition)
                {
                    return;
                }
                _isStart = true;
            }
            //暂停中
            if(sequence.State==RState.Init&&_currentSequenceIndex>=_pausedIndex&&_pausedIndex!=-1)
            {
                return;
            }

            if(sequence.IsWaitNotify)
            {
                if (sequence.State == RState.End)
                {
                    _currentSequenceIndex++;
                }
                return;
            }
            if(sequence.MaterialType==MaterialType.WaferHolder)
            {
                if(sequence.State==RState.End)
                {
                    _currentSequenceIndex++;
                }
                return;
            }
            if (_currentSequenceIndex < _schedulerSequences.Count)
            {
                if (sequence.State == RState.Init)
                {
                    string reason = "";
                    bool sequeceCondition = sequence.SchedulerModule.CheckPrecondition(_schedulerSequences, _currentSequenceIndex,sequence.Parameters,WaferId,ref reason);
                    _sequenceConditionTrigger.CLK = !sequeceCondition;
                    if (sequeceCondition)
                    {
                        bool result = sequence.SchedulerModule.RunProcess(sequence.Recipe,sequence.Parameters,sequence.SynchronousModuleMessages);
                        if (result)
                        {
                            if (State == WaferTaskState.Created)
                            {
                                State = WaferTaskState.Processing;
                                if(OnTaskStart!=null)
                                {
                                    OnTaskStart(WaferId);
                                }
                            }
                            sequence.State = RState.Running;
                            sequence.StartTime = DateTime.Now; 
                            LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferId} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module}");
                        }                        
                    }
                    else
                    {
                        if (_sequenceConditionTrigger.Q)
                        {
                            LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferId} Start {_currentSequenceIndex + 1} sequence {sequence.SchedulerModule.Module} failed,{reason}");
                            if (sequence.SchedulerModule.Module == ModuleName.EfemRobot)
                            {
                                AnalyseSchedulerSrdState(sequence);
                            }
                        }
                    }
                }
                else if (sequence.State == RState.Running)
                {
                    bool hasMatched=!string.IsNullOrEmpty(WaferTaskManager.Instance.GetMatchWaferIdByWaferId(this.WaferId));
                    sequence.SchedulerModule.MonitorProcess(sequence,hasMatched);
                    _sequenceErrorTigger.CLK = sequence.SchedulerModule.IsError;
                    if (sequence.SchedulerModule.IsIdle)
                    {
                        sequence.EndTime = DateTime.Now;
                        sequence.State = RState.End;
                        sequence.ProcessMilliSeconds = sequence.EndTime.Subtract(sequence.StartTime).TotalMilliseconds;
                        LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferId} {_currentSequenceIndex + 1} sequence complete, time length {sequence.ProcessMilliSeconds}");

                        _currentSequenceIndex++;
                    }
                }
                else if(sequence.State==RState.End)
                {
                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferId} {_currentSequenceIndex + 1} sequence is End");

                    _currentSequenceIndex++;
                }
            }
        }
        /// <summary>
        /// 分析错误状态下的调度
        /// </summary>
        private void AnalyseSchedulerSrdState(SchedulerSequence sequence)
        {
            if(!(sequence.Parameters is MoveItem))
            {
                return;
            }
            MoveItem moveItem = sequence.Parameters as MoveItem;
            bool exsitSRD = false;
            if (moveItem.DestinationType == ModuleType.SRD)
            {
                SRDEntity srdEntity1 = Singleton<RouteManager>.Instance.GetModule<SRDEntity>(ModuleName.SRD1.ToString());
                if (srdEntity1 != null&&(srdEntity1.IsBusy||srdEntity1.IsIdle)&&srdEntity1.IsAuto)
                {
                    exsitSRD = true;
                    return;
                }
                SRDEntity srdEntity2 = Singleton<RouteManager>.Instance.GetModule<SRDEntity>(ModuleName.SRD2.ToString());
                if (srdEntity2 != null && (srdEntity2.IsBusy || srdEntity2.IsIdle) && srdEntity2.IsAuto)
                {
                    exsitSRD = true;
                    return;
                }
                if (!exsitSRD)
                {
                    WaferInfo waferInfo = WaferManager.Instance.GetWaferByWaferId(WaferId);
                    if (waferInfo == null || waferInfo.IsEmpty)
                    {
                        return;
                    }
                    WaferManager.Instance.UpdateWaferProcessStatus(moveItem.SourceModule, moveItem.SourceSlot, EnumWaferProcessStatus.MisSrdProcess);
                    MaterialTrackerManager.Instance.UpdateModuleMaterial(moveItem.SourceModule.ToString());
                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{waferInfo.WaferID} status changed to {EnumWaferProcessStatus.MisSrdProcess}");
                    moveItem.DestinationModule = (ModuleName)waferInfo.OriginStation;
                    moveItem.DestinationSlot = waferInfo.OriginSlot;
                    moveItem.DestinationType = ModuleType.LoadPort;
                    LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferId} has no avaible srd changed to {moveItem.DestinationModule}.{moveItem.DestinationSlot}");
                    for(int i = _currentSequenceIndex + 1; i < _schedulerSequences.Count; i++)
                    {
                        SchedulerSequence item = _schedulerSequences[i];
                        item.State = RState.End;
                        LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"{WaferId} skip {i + 1} sequence {item.ModuleType}");
                    }
                }
            }
        }

        /// <summary>
        /// 释放资源
        /// </summary>
        public void Dispose()
        {
            _schedulerSequences.Clear();
        }
        /// <summary>
        /// 检验前置条件
        /// </summary>
        /// <returns></returns>
        private bool CheckStartCondition()
        {
            EfemEntity efemEntity = Singleton<RouteManager>.Instance.EFEM;
            if(!efemEntity.IsIdle)
            {
                return false;
            }
            SchedulerRobot schedulerEfemRobot = (SchedulerRobot)SchedulerManager.Instance.GetScheduler(ModuleName.EfemRobot);
            if(schedulerEfemRobot==null)
            {
                return false;
            }
            if(!schedulerEfemRobot.IsIdle)
            {
                return false;
            }
            if(WaferManager.Instance.CheckHasWafer(ModuleName.EfemRobot,0))
            {
                return false;
            }
            if(WaferManager.Instance.CheckHasWafer(ModuleName.Aligner1, 0))
            {
                return false;
            }
            if(!_pufEntity.IsIdle)
            {
                return false;
            }
            //PUF B面无Wafer
            if(WaferManager.Instance.CheckHasWafer(_pufEntity.Module,1))
            {
                return false;
            }

            //if(!WaferHolderManager.Instance.HasWaferHolder("Loader"))
            //{
            //    return false;
            //}
            LoaderEntity loaderEntity = Singleton<RouteManager>.Instance.GetModule<LoaderEntity>(ModuleName.Loader1.ToString());
            if (loaderEntity == null)
            {
                return false;
            }

            if(!string.IsNullOrEmpty(MateWaferTask))
            {
                WaferTask mateTask=WaferTaskManager.Instance.GetWaferTask(MateWaferTask);
                if(mateTask!=null)
                {
                    if(mateTask.State==WaferTaskState.Created)
                    {
                        return false;
                    }
                }
            }
            else
            {
                if (loaderEntity.IsBusy && loaderEntity.State != (int)LOADERSTATE.WaitForUnload)
                {
                    return false;
                }
            }

            //WaferHolderTask waferHolderTask = WaferTaskManager.Instance.GetWaferHolderTaskByWaferId(WaferId);
            //if (waferHolderTask != null)
            //{
            //    if(waferHolderTask.State==WaferHolderTaskState.Created||waferHolderTask.State==WaferHolderTaskState.Error)
            //    {
            //        return false;
            //    }
            //}
            return true;
        }
        /// <summary>
        /// 同步更新Loader工序完成
        /// </summary>
        public void UpdateLoaderSchedulerSequenceComplete()
        {
            SchedulerSequence schedulerSequence = _schedulerSequences[_currentSequenceIndex];
            if (schedulerSequence != null)
            {
                if (schedulerSequence.ModuleType == ModuleType.PUF&&schedulerSequence.IsWaitNotify)
                {
                    PufSchedulerParameter pufParameter = (PufSchedulerParameter)schedulerSequence.Parameters;
                    if (!pufParameter.IsForward)
                    {
                        schedulerSequence.StartTime = DateTime.Now;
                        schedulerSequence.EndTime = DateTime.Now;
                        schedulerSequence.State = RState.End;
                        schedulerSequence.ProcessMilliSeconds = schedulerSequence.EndTime.Subtract(schedulerSequence.StartTime).TotalMilliseconds;
                        LOG.WriteLog(eEvent.EV_SEQUENCE, "System", $"{WaferId} {_currentSequenceIndex + 1} puf sequence task synchronize notify complete");
                    }
                }
            }
        }
        /// <summary>
        /// 暂停
        /// </summary>
        public void Pause()
        {
            _pausedIndex = _currentSequenceIndex;
        }
        /// <summary>
        /// 恢复
        /// </summary>
        public void Resume()
        {
            _pausedIndex = -1;
        }
        /// <summary>
        /// 移除SRD调度
        /// </summary>
        public void RemoveSrdScheduler()
        {
            WaferInfo waferInfo=WaferManager.Instance.GetWaferByWaferId(WaferId);
            if (waferInfo != null && waferInfo.WaferType == WaferType.Production&&waferInfo.ProcessJob!=null
                &&waferInfo.ProcessJob.SequenceRecipe!=null)
            {
                if (SequenceRecipeManager.Instance.IsContainedSrd(waferInfo.ProcessJob.SequenceRecipe))
                {
                    for(int i=_currentSequenceIndex;i<_schedulerSequences.Count;i++)
                    {
                        SchedulerSequence item= _schedulerSequences[i];
                        if(item.ModuleType==ModuleType.SRD&&i+1<_schedulerSequences.Count&&i>0)
                        {
                            SchedulerSequence preSequence = _schedulerSequences[i - 1];
                            SchedulerSequence nextSequence = _schedulerSequences[i + 1];
                            if (preSequence.ModuleName == ModuleName.EfemRobot&&nextSequence.ModuleName==ModuleName.EfemRobot)
                            {
                                MoveItem moveItem=preSequence.Parameters as MoveItem;
                                MoveItem nextMoveItem=nextSequence.Parameters as MoveItem;
                                moveItem.DestinationModule = nextMoveItem.DestinationModule;
                                moveItem.DestinationSlot= nextMoveItem.DestinationSlot;
                                moveItem.DestinationType= nextMoveItem.DestinationType;
                                _schedulerSequences.RemoveAt(i + 1);
                                _schedulerSequences.RemoveAt(i);
                                LOG.WriteLog(eEvent.EV_SCHEDULER, "System", $"Wafer {WaferId} remove SRD Scheduler");
                            }
                            break;
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 步骤是否进入Loader及之后
        /// </summary>
        /// <returns></returns>
        public bool IsSchedulerForward()
        {
            //0-EfemRobot,1-Aligner,2-EfemRobot,3-Puf(正向),4-PUF(工艺结束返回)
            return _currentSequenceIndex < 4;
        }
    }
}