using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.Routine;
using CyberX8_Core;
using CyberX8_RT.Devices.AXIS;
using CyberX8_RT.Devices.SRD;
using System;
using System.Collections.Generic;
using MECF.Framework.Common.Utilities;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.CommonData.SRD;
using Aitex.Core.RT.SCCore;
using Aitex.Core.RT.Device;
using CyberX8_RT.Devices.Facilities;
using Aitex.Core.Util;
using CyberX8_RT.Modules.Transporter;
using MECF.Framework.Common.WaferHolder;
using MECF.Framework.Common.Persistent.SRD;
namespace CyberX8_RT.Modules.SRD
{
    public class SRDProcessRecipeRoutine : RoutineBase, IRoutine
    {
        #region 常量
        private const int LOTTRACK_TIME = 1000;
        #endregion
        private enum SRDProcessState
        {
            Ready,    
            StartLoader,
            Loading,
            StartRunRecipe,
            RunReciping,
            StartUnloader,
            Unloading,
            CycleEnd,
            End
        }
        #region 内部变量
        /// 
        /// 次数
        /// 
        private int _cycleCount = 0;
        /// 
        /// Rotation Axis
        /// 
        private JetAxisBase _rotationAxis;
        /// 
        /// Arm Axis
        /// 
        private JetAxisBase _armAxis;
        /// 
        /// SRD Recipe
        /// 
        private SrdRecipe _srdRecipe;
        /// 
        /// 设备对象
        /// 
        private SrdCommonDevice _srdCommonDevice;
        /// 
        /// Run Recipe Routine
        /// 
        private SRDRunRecipeRoutine _runRecipeRoutine;
        /// 
        /// Unloader Routine
        /// 
        private SRDUnloaderRoutine _unloaderRoutine;
        /// 
        /// Loader Routine
        /// 
        private SRDLoaderRoutine _loaderRoutine;
        /// 
        /// lock track time
        /// 
        private DateTime _lotTackTime = DateTime.Now;
        /// 
        /// LotTrack数据
        /// 
        private List _datas = new List();
        /// 
        /// LotTrack文件头数据
        /// 
        private LotTrackFileHeaderCommonData _header = new LotTrackFileHeaderCommonData();        
        /// 
        /// Facilities
        /// 
        private SystemFacilities _facilities;
        /// 
        /// Manual模式
        /// 
        private bool _isManual = false;
        #endregion
        #region 属性
        /// 
        /// 当前子状态机
        /// 
        public string CurrentStateMachine
        { 
            get { return GetCurrentStateMachine(); } 
        }
        /// 
        /// 当前cycle次数
        /// 
        public int AchievedCycle { get { return Runner.LoopCounter; } }
        /// 
        /// 是否正在用水
        /// 
        public bool IsUsingWater { get { return _runRecipeRoutine.IsUsingWater; } }
        /// 
        /// LotTrack数据
        /// 
        public List SRDLotTrackDatas { get { return _datas; } }
        /// 
        /// LotTrack文件头数据
        /// 
        public LotTrackFileHeaderCommonData SRDLotTrackHeaderDatas { get { return _header; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public SRDProcessRecipeRoutine(string module, JetAxisBase rotationAxis, JetAxisBase armAxis, SrdCommonDevice srdCommon) : base(module)
        {
            _rotationAxis = rotationAxis;
            _armAxis = armAxis;
            _srdCommonDevice = srdCommon;
            _runRecipeRoutine = new SRDRunRecipeRoutine(module);
            _unloaderRoutine= new SRDUnloaderRoutine(module);
            _loaderRoutine = new SRDLoaderRoutine(module);
        }
        /// 
        /// 取消
        /// 
        public void Abort()
        {
            if(_unloaderRoutine.Monitor() == RState.Running)
            {
                _unloaderRoutine.Abort();
            }
            if (_runRecipeRoutine.Monitor() == RState.Running)
            {
                _runRecipeRoutine.Abort();
            }
            if (_loaderRoutine.Monitor() == RState.Running)
            {
                _loaderRoutine.Abort();
            }
            Runner.Stop("Manual Abort");
            if (_srdCommonDevice != null)
            {
                _srdCommonDevice.EnterErrorOperation();
            }
        }
        /// 
        /// 监控
        /// 
        /// 
        /// 
        public RState Monitor()
        {
            LottrackRecord();
            Runner.LoopStart(SRDProcessState.Ready, "Process Recipe Start", _cycleCount, NullFun, _delay_1ms)
                .LoopRunIf(SRDProcessState.StartLoader, !_isManual,() => { return StartLoader(); }, _delay_1ms)
                .LoopRunIfWithStopStatus(SRDProcessState.Loading, !_isManual, CheckLoaderEndStatus, CheckLoaderErrorStatus)
                .LoopRun(SRDProcessState.StartRunRecipe, () => { return StartRunRecipe(); }, _delay_1ms)
                .LoopRunWithStopStatus(SRDProcessState.RunReciping, CheckRunRecipeEndStatus, CheckRunRecipeErrorStatus)
                .LoopRunIf(SRDProcessState.StartUnloader, !_isManual, () => { return StartUnloader(); }, _delay_1ms)
                .LoopRunIfWithStopStatus(SRDProcessState.Unloading, !_isManual, CheckUnloaderEndStatus, CheckUnloaderErrorStatus)
                .LoopEnd(SRDProcessState.CycleEnd, NullFun, _delay_1ms)             
                .End(SRDProcessState.End, NullFun, _delay_1ms);
            return Runner.Status;
        }
        /// 
        /// 启动
        /// 
        /// 
        /// 
        /// 
        public RState Start(params object[] objects)
        {
            _srdRecipe = objects[0] as SrdRecipe;
            if (_srdRecipe == null)
            {
                LOG.WriteLog(eEvent.ERR_SRD, Module.ToString(), " recipe is null");
                return RState.Failed;
            }
            _cycleCount = (int)objects[1];
            if (_cycleCount == 0)
            {
                return RState.End;
            }
            _isManual = false;
            SRDPersistentValue srdPersistentValue = SRDPersistentManager.Instance.GetModulePersistentValue(Module);
            if(srdPersistentValue.OperatingMode.Equals("Manual")) _isManual = true;
            _header.SoftWareVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString();
            _header.Recipe = $"{_srdRecipe.Ppid}.srd.rcp";
            if (SC.ContainsItem("System.ToolID")) _header.ToolID = SC.GetStringValue("System.ToolID");
            _facilities = DEVICE.GetDevice("System.Facilities");
            if (_facilities == null)
            {
                LOG.WriteLog(eEvent.ERR_SRD, Module, "Facility is null");
                return RState.Failed;
            }
            _datas.Clear();
            _lotTackTime = DateTime.Now;
            return Runner.Start(Module, "Process Recipe");
        }
        #region Loader
        /// 
        /// 启动LoaderRoutine
        /// 
        /// 
        /// 
        private bool StartLoader()
        {
            bool result = _loaderRoutine.Start() == RState.Running;
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0);
            }
            return result;
        }
        /// 
        /// 检验LoaderRoutine完成情况 
        /// 
        /// 
        private bool CheckLoaderEndStatus()
        {
            return CommonFunction.CheckRoutineEndState(_loaderRoutine);
        }
        /// 
        /// 检验LoaderRoutine错误情况 
        /// 
        /// 
        private bool CheckLoaderErrorStatus()
        {
            bool result = CommonFunction.CheckRoutineStopState(_loaderRoutine);
            if (result)
            {
                //AddLotTrackData();
                if (_srdCommonDevice != null)
                {
                    _srdCommonDevice.EnterErrorOperation();
                }
                NotifyError(eEvent.ERR_SRD, _loaderRoutine.ErrorMsg, 0);
            }
            return result;
        }
        #endregion
        #region RunRecipe
        /// 
        /// 启动状态机
        /// 
        /// 
        /// 
        private bool StartRunRecipe()
        {
            bool result = _runRecipeRoutine.Start(_srdRecipe)==RState.Running;           
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_SRD, Module.ToString(), $"Start Run Recipe, recipe[{_srdRecipe.Ppid}] times[{_cycleCount + 1}]");
            }
            else
            {
                NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0);
            }
            return result;
        }
        /// 
        /// 检验RunRecipeRoutine完成情况 
        /// 
        /// 
        private bool CheckRunRecipeEndStatus()
        {
            return CommonFunction.CheckRoutineEndState(_runRecipeRoutine);
        }
        /// 
        /// 检验RunRecipeRoutine错误情况 
        /// 
        /// 
        private bool CheckRunRecipeErrorStatus()
        {
            bool result = CommonFunction.CheckRoutineStopState(_runRecipeRoutine);
            if (result)
            {
                //AddLotTrackData(); 
                if (_srdCommonDevice != null)
                {
                    _srdCommonDevice.EnterErrorOperation();
                }
                NotifyError(eEvent.ERR_SRD, _runRecipeRoutine.ErrorMsg, 0);
            }
            return result;           
        }
        #endregion
        #region Unloader
        /// 
        /// 启动UnloaderRoutine
        /// 
        /// 
        /// 
        private bool StartUnloader()
        {
            bool result= _unloaderRoutine.Start(false) == RState.Running;
            if (!result)
            {
                NotifyError(eEvent.ERR_SRD,_unloaderRoutine.ErrorMsg, 0);
            }
            return result;
        }
        /// 
        /// 检验UnloaderRoutine完成情况 
        /// 
        /// 
        private bool CheckUnloaderEndStatus()
        {
            return CommonFunction.CheckRoutineEndState(_unloaderRoutine);
        }
        /// 
        /// 检验UnloaderRoutine错误情况 
        /// 
        /// 
        private bool CheckUnloaderErrorStatus()
        {
            bool result= CommonFunction.CheckRoutineStopState(_unloaderRoutine);
            if (result)
            {
                //AddLotTrackData();
                NotifyError(eEvent.ERR_SRD, _unloaderRoutine.ErrorMsg, 0);
            }
            return result;
        }
        
        #endregion
              
        /// 
        /// 获取当前子状态机
        /// 
        private string GetCurrentStateMachine()
        {
            string result;
            if(Runner.CurrentStep.ToString() == "Ready")
            {
                result = "Ready";
            }
            else if(Runner.CurrentStep.ToString().Contains("RunReciping"))
            {
                result = _runRecipeRoutine.CurrentStep;
            }
            else if(Runner.CurrentStep.ToString().Contains("Unloading"))
            {
                result = _unloaderRoutine.CurrentStep;
            }
            else
            {
                result = "End";
            }
            return result;
        }
        /// 
        /// 记录Lottrack
        /// 
        private void LottrackRecord()
        {
            //记录Lottrack
            if (DateTime.Now.Subtract(_lotTackTime).TotalMilliseconds >= LOTTRACK_TIME)
            {
                //AddLotTrackData();
                _lotTackTime = DateTime.Now;
            }
        }
        
        /// 
        /// 获取Lot Track数据
        /// 
        /// 
        private void AddLotTrackData()
        {
            SRDLotTrackData data = new SRDLotTrackData();
            data.TimeStamp = DateTime.Now;
            data.StateMachine = GetCurrentStateMachine();
            data.ArmPosition = _armAxis.MotionData.MotorPosition;
            data.WaterPressure = _srdCommonDevice.CommonData.WaterPressure;
            data.WaferPresence =  $"{_srdCommonDevice.WaferPresence}:{_srdCommonDevice.CommonData.WaferPresence}";
            data.ChuckVacuumOn = _srdCommonDevice.CommonData.ChuckVacuum;
            data.ChuckVacuumPressure = _srdCommonDevice.CommonData.VacuumValue;
            data.ArmTorque = _armAxis.MotionData.ActualTorque;
            data.SpinTorque = _rotationAxis.MotionData.ActualTorque;
            data.RotationSpeed = _rotationAxis.MotionData.ActualVelocity;
            data.N2BelowOn = false;
            data.WaterAbove = _srdCommonDevice.CommonData.WaterAbove;
            data.WaterBelow = _srdCommonDevice.CommonData.WaterBelow;
            data.ExhaustOn = _srdCommonDevice.CommonData.ExhaustOn;
            data.LoaderDIEnable = _facilities.LoaderDiEnable;
            data.WaterFlow = 0;
            _datas.Add(data);
        }
        /// 
        /// 重试
        /// 
        /// 
        public RState Retry(int step)
        {
            List preStepIds = new List();
            return Runner.Retry(SRDProcessState.Ready, preStepIds, Module, "RunRecipe Retry");
        }
        /// 
        /// 检验前面完成状态
        /// 
        /// 
        public bool CheckCompleteCondition(int index)
        {
            if (_armAxis.IsRun)
            {
                NotifyError(eEvent.ERR_SRD, "Arm axis is run", 0);
                return false;
            }
            if (!_armAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_SRD, "Arm axis is not homed", 0);
                return false;
            }
            if (_rotationAxis.IsRun)
            {
                NotifyError(eEvent.ERR_SRD, "Rotation axis is run", 0);
                return false;
            }
            if (!_rotationAxis.IsHomed)
            {
                NotifyError(eEvent.ERR_SRD, "Rotation axis is not homed", 0);
                return false;
            }
            if (!_srdCommonDevice.CommonData.ChuckVacuum)
            {
                NotifyError(eEvent.ERR_SRD, "Vacuum is not released", 0);
                return false;
            }
            if (!_srdCommonDevice.CommonData.DoorOpened)
            {
                NotifyError(eEvent.ERR_SRD, "Door is not opened", 0);
                return false;
            }
            return true;
        }
    }
}