using Aitex.Core.RT.Fsm;
using Aitex.Core.Util;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using CyberX8_Core;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Loader;
using CyberX8_RT.Modules.Transporter;
using CyberX8_RT.Modules.PUF;
using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Syndication;
using System.Text;
using System.Threading.Tasks;
using CyberX8_RT.Modules.Prewet;
using Aitex.Core.RT.Device;
using CyberX8_RT.Devices.AXIS;
using MECF.Framework.Common.WaferHolder;
using Aitex.Core.RT.Log;
using MECF.Framework.Common.Schedulers;
namespace CyberX8_RT.Schedulers.Transporter
{
    public class SchedulerLoaderTransporter : SchedulerModule
    {
        private enum TransBufferToLoaderStep
        {
            None,
            NotifyLoaderPrepare,
            WaitLoaderPrePare,
            PickUpValidate,
            PickUpValidateMoveto,
            Place,
            End
        }
        private enum TransporterFlip
        {
            None,
            WaitPickUp,
            LoaderFlip,
            WaitLoader,
            WaitPlace,
        }
        #region 内部变量
        private LoaderEntity _loaderEntity;
        private TransporterEntity _loaderTransporterEntity;
        private TransporterEntity _processTransporterEntity;
        private TransBufferToLoaderStep _transBufferToLoaderStep = TransBufferToLoaderStep.None;
        private SchedulerPostMsg _schedulerPostMsg = new SchedulerPostMsg();
        private bool _postMsgResult = false;
        private TransporterFlip _transporterFlip=TransporterFlip.None;
        #endregion
        #region 属性
        public override bool IsIdle
        {
            get { return _state == RState.End; }
        }
        public  bool IsBusy
        {
            get { return _state == RState.Running; }
        }
        public override bool IsError
        {
            get { return _state==RState.Failed||_state==RState.Timeout; }
        }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public SchedulerLoaderTransporter(ModuleName module) : base(module.ToString())
        {
            _loaderEntity = Singleton.Instance.GetModule(ModuleName.Loader1.ToString());
            _loaderTransporterEntity = Singleton.Instance.GetModule(ModuleName.Transporter2.ToString());
            _processTransporterEntity = Singleton.Instance.GetModule(ModuleName.Transporter1.ToString());
        }
        /// 
        /// 执行
        /// 
        /// 
        /// 
        public override bool RunProcess(object recipe, object parameter,List syncMessages)
        {
            if (parameter==null)
            {
                return false;
            }
            TransporterAction action = (TransporterAction)parameter;
            if (action.ActionMsg == TransporterMSG.Transfer)
            {
                SynchorinzeModuleMessages(syncMessages);
                WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)action.Parameter;
                if (waferHolderMoveItem.SourceModule != ModuleName.Unknown && waferHolderMoveItem.DestModule != ModuleName.Unknown)
                {
                    SchedulerProcessTransporter schedulerProcessTransporter = (SchedulerProcessTransporter)SchedulerManager.Instance.GetScheduler(ModuleName.Transporter1);
                    if (schedulerProcessTransporter.IsBusy && _processTransporterEntity.IsIdle)
                    {
                        return false;
                    }
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.SourceModule.ToString()))
                    {
                        return false;
                    }
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.DestModule.ToString()))
                    {
                        return false;
                    }
                    string strSource = waferHolderMoveItem.SourceModule.ToString();
                    if (waferHolderMoveItem.SourceModule == ModuleName.Loader1)
                    {
                        strSource = "Loader";
                    }
                    //由于PickUpValidate可能存在校验失败的现象
                    if (!WaferHolderManager.Instance.HasWaferHolder(strSource) && _loaderTransporterEntity.State != (int)TransporterState.PickUpValidateComplete)
                    {
                        return false;
                    }
                    string strDest = waferHolderMoveItem.DestModule.ToString();
                    if (waferHolderMoveItem.DestModule == ModuleName.Loader1)
                    {
                        strDest = "Loader";
                    }
                    if (WaferHolderManager.Instance.HasWaferHolder(strDest))
                    {
                        return false;
                    }
                    if (waferHolderMoveItem.DestModule == ModuleName.Loader1)
                    {
                        return TransferWaferHolderToLoader(waferHolderMoveItem);
                    }
                    else if (waferHolderMoveItem.SourceModule == ModuleName.Loader1)
                    {
                        return TransWaferHolderFromLoader(waferHolderMoveItem);
                    }
                    else if (waferHolderMoveItem.SourceModuleType != ModuleType.Loader && waferHolderMoveItem.DestModuleType != ModuleType.Loader)
                    {
                        return TransferWaferHolderNonLoader(waferHolderMoveItem);
                    }
                }
            }
            else if (action.ActionMsg == TransporterMSG.Flip)
            {
                return FlipLoader();
            }
            return true;
        }
        /// 
        /// Loader 开始Flip
        /// 
        /// 
        private bool FlipLoader()
        {
            if (_loaderEntity.WaferHolderInfo == null)
            {
                return false;
            }
            if (_loaderTransporterEntity.WaferHolderInfo != null)
            {
                return false;
            }
            bool result = _loaderTransporterEntity.CheckToPostMessage(eEvent.WARN_TRANSPORTER,
                Module.ToString(), (int)TransporterMSG.PickUpFrom, "Loader");
            if (result)
            {
                _state = RState.Running;
                _schedulerPostMsg.Reset();
                _postMsgResult = false;
                _transporterFlip = TransporterFlip.WaitPickUp;
            }
            return result;
        }
        /// 
        /// WaferHolder从Loader移动至Buffer
        /// 
        private bool TransWaferHolderFromLoader(WaferHolderMoveItem waferHolderMoveItem)
        {
            if (_loaderEntity.IsBusy)
            {
                return false;
            }
            if (_loaderEntity.WaferHolderInfo == null)
            {
                return false;
            }
            bool result = _loaderTransporterEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_TRANSPORTER,
                Module.ToString(), (int)TransporterMSG.Transfer, "Loader", waferHolderMoveItem.DestModule.ToString());
            if (result)
            {
                _state = RState.Running;
                _schedulerPostMsg.Reset();
                _postMsgResult = false;
            }
            return result;
        }
        /// 
        /// WaferHolder从Buffer移动至Loader
        /// 
        private bool TransferWaferHolderToLoader(WaferHolderMoveItem waferHolderMoveItem)
        {
            if (_loaderEntity.WaferHolderInfo != null)
            {
                return false;
            }
            if (_loaderEntity.IsIdle)
            {
                bool loaderResult = _loaderEntity.CheckToPostMessage(eEvent.WARN_LOADER,
                    _loaderEntity.Module.ToString(), (int)LoaderMSG.PrepareForPlace);
                if (loaderResult)
                {
                    _transBufferToLoaderStep = TransBufferToLoaderStep.WaitLoaderPrePare;
                }
                return false;
            }
            else if (_loaderEntity.State == (int)LOADERSTATE.WaitForUnload&&_transBufferToLoaderStep(Aitex.Core.RT.Log.eEvent.WARN_TRANSPORTER,
                    Module.ToString(), (int)TransporterMSG.PickUpValidate, waferHolderMoveItem.SourceModule.ToString());
                if (result)
                {
                    _transBufferToLoaderStep= TransBufferToLoaderStep.PickUpValidateMoveto;
                    _state = RState.Running;
                    _schedulerPostMsg.Reset();
                    _postMsgResult = false;
                    return true;
                }
            }
            return false;
        }
        /// 
        /// 传输WaferHolder(无WaferHolder)
        /// 
        /// 
        private bool TransferWaferHolderNonLoader(WaferHolderMoveItem waferHolderMoveItem)
        {
            IModuleEntity moduleEntity = Singleton.Instance.GetModule(waferHolderMoveItem.DestModule.ToString());
            if (moduleEntity != null)
            {
                if (waferHolderMoveItem.SourceModule == ModuleName.Unknown || waferHolderMoveItem.DestModule == ModuleName.Unknown)
                {
                    return false;
                }
                if (moduleEntity.Module == ModuleName.Prewet1)
                {
                    PrewetEntity prewetEntity = moduleEntity as PrewetEntity;
                    if(prewetEntity.State!=(int)PrewetState.WaitForPlace)
                    {
                        return false;
                    }
                }
                else
                {
                    if (!moduleEntity.IsIdle)
                    {
                        return false;
                    }
                }
                if (waferHolderMoveItem.SourceModule != ModuleName.Unknown)
                {
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.SourceModule.ToString()))
                    {
                        return false;
                    }
                }
                if (waferHolderMoveItem.DestModule != ModuleName.Unknown)
                {
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.DestModule.ToString()))
                    {
                        return false;
                    }
                }
                bool result = _loaderTransporterEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_TRANSPORTER,
                    Module.ToString(), (int)TransporterMSG.Transfer, waferHolderMoveItem.SourceModule.ToString(), waferHolderMoveItem.DestModule.ToString());
                if (result)
                {
                    _state = RState.Running;
                    _postMsgResult = false;
                    _schedulerPostMsg.Reset();
                }
                return result;
            }
            return false;
        }
        /// 
        /// 监控执行
        /// 
        /// 
        public override bool MonitorProcess(SchedulerSequence schedulerSequence, bool hasMatchWafer)
        {
            TransporterAction action=schedulerSequence.Parameters as TransporterAction;
            if (action.ActionMsg == TransporterMSG.Transfer)
            {
                WaferHolderMoveItem moveItem = action.Parameter as WaferHolderMoveItem;
                //检验PostMsg的结果
                if (!_postMsgResult)
                {
                    if (_loaderTransporterEntity.IsError)
                    {
                        return false;
                    }
                    _postMsgResult = CheckPostMsg(moveItem);
                    if (!_postMsgResult)
                    {
                        return false;
                    }
                }
                if (moveItem.DestModule == ModuleName.Loader1)
                {
                    if (_transBufferToLoaderStep == TransBufferToLoaderStep.PickUpValidateMoveto)
                    {
                        if (_loaderTransporterEntity.IsIdle)
                        {
                            _state = RState.Failed;
                            _transBufferToLoaderStep = TransBufferToLoaderStep.None;
                            return false;
                        }
                        if (_loaderTransporterEntity.State == (int)TransporterState.PickUpValidateComplete)
                        {
                            if (!_loaderTransporterEntity.CheckOtherEntityStatus("Loader"))
                            {
                                return false;
                            }
                            bool result = _loaderTransporterEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_TRANSPORTER,
                                    Module.ToString(), (int)TransporterMSG.MoveTo, "Loader");
                            if (result)
                            {
                                _transBufferToLoaderStep = TransBufferToLoaderStep.Place;
                            }
                        }
                        return true;
                    }
                    else if (_transBufferToLoaderStep == TransBufferToLoaderStep.Place)
                    {
                        if (_loaderTransporterEntity.State == (int)TransporterState.ValidateMoveToComplete)
                        {
                            bool result = _loaderTransporterEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_TRANSPORTER,
                                    Module.ToString(), (int)TransporterMSG.Place, "Loader");
                            if (result)
                            {
                                _transBufferToLoaderStep = TransBufferToLoaderStep.End;
                            }
                        }
                        return true;
                    }
                }
                if (_loaderTransporterEntity.IsIdle)
                {
                    if (_loaderTransporterEntity.WaferHolderInfo != null)
                    {
                        return false;
                    }
                    PrewetPickComplete(schedulerSequence);
                    _state = RState.End;
                    _transBufferToLoaderStep=TransBufferToLoaderStep.None;
                }
            }
            else if (action.ActionMsg == TransporterMSG.Flip)
            {
                LoaderTransporterFlip(action.Parameter.ToString());
            }
            return true;
        }
        /// 
        /// Flip
        /// 
        private void LoaderTransporterFlip(string strTransporter)
        {
            if(_transporterFlip==TransporterFlip.WaitPickUp)
            {
                //检验PostMsg的结果
                if (!_postMsgResult)
                {
                    if (_loaderTransporterEntity.IsError)
                    {
                        return;
                    }
                    _postMsgResult = _schedulerPostMsg.PostMsg(_loaderTransporterEntity, _loaderTransporterEntity.State,
                        eEvent.WARN_TRANSPORTER, Module.ToString(), (int)TransporterMSG.PickUpFrom,(int)TransporterState.PickUping, "Loader");
                    if (!_postMsgResult)
                    {
                        return;
                    }
                }
                if (_loaderTransporterEntity.IsIdle && _loaderTransporterEntity.WaferHolderInfo != null)
                {
                    _transporterFlip = TransporterFlip.LoaderFlip;
                }
            }
            else if (_transporterFlip == TransporterFlip.LoaderFlip)
            {
                bool result = _loaderEntity.CheckToPostMessage(eEvent.WARN_LOADER, Module.ToString(), (int)LoaderMSG.PrepareForPlace, strTransporter);
                if (result)
                {
                    _transporterFlip = TransporterFlip.WaitLoader;
                }
            }
            else if(_transporterFlip==TransporterFlip.WaitLoader)
            {
                if (_loaderEntity.State == (int)LOADERSTATE.WaitForUnload)
                {
                    bool result = _loaderTransporterEntity.CheckToPostMessage(eEvent.WARN_TRANSPORTER,
                                    Module.ToString(), (int)TransporterMSG.Place, "Loader");
                    if (result)
                    {
                        _transporterFlip = TransporterFlip.WaitPlace;
                    }
                }
            }
            else if (_transporterFlip == TransporterFlip.WaitPlace)
            {
                if (_loaderTransporterEntity.IsIdle && _loaderTransporterEntity.WaferHolderInfo == null)
                {
                    _state = RState.End;
                    _transporterFlip = TransporterFlip.None;
                }
            }
        } 
        /// 
        /// 检验PostMsg的结果
        /// 
        /// 
        /// 
        private bool CheckPostMsg(WaferHolderMoveItem waferHolderMoveItem)
        {
            if (waferHolderMoveItem.DestModule == ModuleName.Loader1)
            {
                return _schedulerPostMsg.PostMsg(_loaderTransporterEntity, _loaderTransporterEntity.State, 
                    eEvent.WARN_TRANSPORTER,Module.ToString(), (int)TransporterMSG.PickUpValidate, 
                    (int)TransporterState.PickUpValidating, waferHolderMoveItem.SourceModule.ToString());
            }
            else
            {
                return _schedulerPostMsg.PostMsg(_loaderTransporterEntity, _loaderTransporterEntity.State,
                    eEvent.WARN_TRANSPORTER, Module.ToString(), (int)TransporterMSG.Transfer,
                    (int)TransporterState.Transfering, waferHolderMoveItem.SourceModule.ToString(),waferHolderMoveItem.DestModule.ToString());
            }
        }
        /// 
        /// PrewetPick完成事件
        /// 
        private void PrewetPickComplete(SchedulerSequence sequence)
        {
            if (sequence.Parameters is TransporterAction)
            {
                TransporterAction action = (TransporterAction)sequence.Parameters;
                if (action.ActionMsg!=TransporterMSG.Transfer)
                {
                    return;
                }
                WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)action.Parameter;
                if (waferHolderMoveItem.SourceModule == ModuleName.Prewet1)
                {
                    PrewetEntity prewetEntity = Singleton.Instance.GetModule(ModuleName.Prewet1.ToString());
                    if (prewetEntity.State == (int)PrewetState.WaitForPick)
                    {
                        prewetEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_PREWET, ModuleName.Prewet1.ToString(),
                            (int)PrewetMsg.PickComplete);
                    }
                }
            }
        }
        /// 
        /// 检验前置条件
        /// 
        /// 
        /// 
        /// 
        public override bool CheckPrecondition(List schedulerSequences, int sequenceIndex, object parameter, string materialId, ref string reason)
        {
            _state = RState.Init;
            if(!(parameter is TransporterAction))
            {
                reason = "parameter is not TransporterAction";
                return false;
            }
            TransporterAction action = (TransporterAction)parameter;
            if (_state == RState.Running)
            {
                reason = "scheduler module is already running";
                return false;
            }
            if (_loaderTransporterEntity.IsBusy)
            {
                reason = "loader transporter entity is busy";
                return false;
            }
            if (_loaderTransporterEntity.WaferHolderInfo != null&& _loaderTransporterEntity.State != (int)TransporterState.PickUpValidateComplete)
            {
                reason = "loader transporter has wafer shuttle,but state is not PickUpValidateComplete";
                return false;
            }
            //电机是否还在执行动作
            JetAxisBase gantryAxis = DEVICE.GetDevice($"{ModuleName.Transporter2}.Gantry");
            if (gantryAxis == null)
            {
                reason = "loader transporter gantry is null";
                return false;
            }
            if (gantryAxis.Status == RState.Running)
            {
                reason = "loader transporter gantry is running";
                return false;
            }
            JetAxisBase elevatorAxis = DEVICE.GetDevice($"{ModuleName.Transporter2}.Elevator");
            if (elevatorAxis == null)
            {
                reason = "loader transporter elevator is null";
                return false;
            }
            if (elevatorAxis.Status == RState.Running)
            {
                reason = "loader transporter elevator is running";
                return false;
            }
            if (action.ActionMsg == TransporterMSG.Transfer)
            {
                WaferHolderMoveItem waferHolderMoveItem = (WaferHolderMoveItem)action.Parameter;
                //更新未知目标模块
                bool result = UpdateUnkownTargetModule(schedulerSequences, waferHolderMoveItem, sequenceIndex, materialId);
                if (!result)
                {
                    reason = "loader transporter moveitem target module is unknown";
                    return false;
                }
                //更新未知源模块
                UpdateUnkownSourceModule(schedulerSequences, waferHolderMoveItem, sequenceIndex, materialId);
                if (waferHolderMoveItem.SourceModule != ModuleName.Unknown)
                {
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.SourceModule.ToString()))
                    {
                        reason = $"loader transporter {waferHolderMoveItem.SourceModule} conflict process transporter";
                        return false;
                    }
                }
                if (waferHolderMoveItem.DestModule != ModuleName.Unknown)
                {
                    if (!_loaderTransporterEntity.CheckOtherEntityStatus(waferHolderMoveItem.DestModule.ToString()))
                    {
                        reason = $"loader transporter {waferHolderMoveItem.DestModule} conflict process transporter";
                        return false;
                    }
                }
                //目标为Prewet
                if (waferHolderMoveItem.DestModule == ModuleName.Prewet1)
                {
                    bool prewetCondition = CheckTargetPrewetCondition();
                    if (!prewetCondition)
                    {
                        reason = "loader transporter destmodule prewet condition is not avaible";
                    }
                    return prewetCondition;
                }
                //源为Prewet
                if (waferHolderMoveItem.SourceModule == ModuleName.Prewet1)
                {
                    bool prewetCondition = CheckSourcePrewetCondition();
                    if (!prewetCondition)
                    {
                        reason = "loader transporter sourcemodule prewet condition is not avaible";
                    }
                }
            }
            return true;
        }
        /// 
        /// 更新未知目标模块
        /// 
        private bool UpdateUnkownTargetModule(List schedulerSequences, WaferHolderMoveItem waferHolderMoveItem, int sequenceIndex,string materialId)
        {
            SchedulerSequence currentSequence = schedulerSequences[sequenceIndex];
            if (waferHolderMoveItem.DestModule == ModuleName.Unknown)
            {
                ModuleName moduleName = SchedulerSequenceManager.Instance.GetAvaibleEmptyModuleCell(waferHolderMoveItem.DestModuleType,currentSequence.SequenceType);
                if (moduleName == ModuleName.Unknown)
                {
                    return false;
                }
                else
                {
                    waferHolderMoveItem.DestModule = moduleName;
                    if (sequenceIndex + 1 < schedulerSequences.Count)
                    {
                        SchedulerSequence sequence = schedulerSequences[sequenceIndex + 1];
                        if (sequence.SchedulerModule == null)
                        {
                            sequence.SchedulerModule = SchedulerManager.Instance.GetScheduler(moduleName);
                            sequence.ModuleName = moduleName;
                            LOG.WriteLog(eEvent.INFO_TRANSPORTER, Module.ToString(), $"{materialId} loadertransporter confirm source module {moduleName}");
                        }
                    }
                }
            }
            return true;
        }
        /// 
        /// 更新未知源模块
        /// 
        private void UpdateUnkownSourceModule(List schedulerSequences, WaferHolderMoveItem waferHolderMoveItem,int sequenceIndex,string materialId)
        {
            if (waferHolderMoveItem.SourceModule == ModuleName.Unknown)
            {
                if (sequenceIndex >= 1 && sequenceIndex - 1 < schedulerSequences.Count)
                {
                    SchedulerSequence preSchedulerSequence = schedulerSequences[sequenceIndex - 1];
                    if (preSchedulerSequence != null && preSchedulerSequence.SchedulerModule != null)
                    {
                        waferHolderMoveItem.SourceModule = preSchedulerSequence.SchedulerModule.Module;
                        LOG.WriteLog(eEvent.INFO_TRANSPORTER, Module.ToString(), $"{materialId} loadertransporter confirm source module {preSchedulerSequence.SchedulerModule.Module}");
                    }
                }
            }
        }
        /// 
        /// 检验目标Prewet前置条件
        /// 
        /// 
        private bool CheckTargetPrewetCondition()
        {
            PrewetEntity prewetEntity = Singleton.Instance.GetModule(ModuleName.Prewet1.ToString());
            if(prewetEntity.IsIdle)
            {
                prewetEntity.CheckToPostMessage(Aitex.Core.RT.Log.eEvent.WARN_PREWET, ModuleName.Prewet1.ToString(),
                    (int)PrewetMsg.PrepareToPlace);
            }
            else if(prewetEntity.State==(int)PrewetState.WaitForPlace)
            {
                return true;
            }
            return false;
        }
        /// 
        /// 检验源Prewet前置条件
        /// 
        /// 
        private bool CheckSourcePrewetCondition()
        {
            PrewetEntity prewetEntity = Singleton.Instance.GetModule(ModuleName.Prewet1.ToString());
            if (prewetEntity.State == (int)PrewetState.WaitForPick||prewetEntity.IsError)
            {
                return true;
            }
            return false;
        }
        public override void ResetTask()
        {
            base.ResetTask();
            _schedulerPostMsg.Reset();
            _postMsgResult = false;
        }
    }
}