using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Fsm;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using Aitex.Core.Utilities;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.WaferHolder;
using CyberX8_Core;
using System;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.Persistent.Reservoirs;
using CyberX8_RT.Modules.Reservoir;
using Aitex.Core.RT.OperationCenter;
using MECF.Framework.Common.RecipeCenter;
using Aitex.Core.RT.RecipeCenter;
using MECF.Framework.Common.SubstrateTrackings;
using CyberX8_RT.Devices.Metal;
using Aitex.Core.RT.Device;
using CyberX8_RT.Devices.Reservoir;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.ProcessCell;
using Aitex.Core.RT.SCCore;
namespace CyberX8_RT.Modules.Metal
{
    public class MetalEntity : Entity, IEntity, IModuleEntity
    {
        #region 常量
        private const string STRATUS = "Stratus";
        private const string AUTO = "Auto";
        private const string MANUAL = "Manual";
        private const string DISABLED= "Disabled";
        private const string ENGINEERING = "Engineering";
        private const string PRODUCTION = "Production";
        #endregion
        #region 内部变量
        /// 
        /// 已经完成的Cycle次数
        /// 
        private int _achievedCycle = 0;
        /// 
        /// Metal项
        /// 
        private MetalItem _metalItem;
        /// 
        /// 持久化对象
        /// 
        private MetalPersistentValue _persistentValue;
        /// 
        /// c&m Initialize routine
        /// 
        private CompactEmbranceInitializeRoutine _compactEmbranceInitializeRoutine;
        /// 
        /// C&M Runrecipe routine
        /// 
        private CompactEmbranceRunRecipeRoutine _compactEmbranceRunRecipeRoutine;
        /// 
        /// S&H Initialize Routine
        /// 
        private StandardHotInitializeRoutine _standardHotInitializeRoutine;
        /// 
        /// S&H RunRecipe Routine
        /// 
        private StandardHotRunRecipeRoutine _standardHotRunRecipeRoutine;
        /// 
        /// Current short test routine
        /// 
        private CurrentShortTestRoutine _currentShortTestRoutine;
        /// 
        /// 当前Recipe
        /// 
        private DepRecipe _currentRecipe = null;
        /// 
        /// recipe时间
        /// 
        private int _recipeTime;
        /// 
        /// 循环次数
        /// 
        private int _cycle = 0;
        /// 
        /// 运行Recipe面
        /// 
        private string _recipeSide = "";
        /// 
        /// 当前RunRecipe Routine
        /// 
        private RoutineBase _currentRunRecipeRoutine;
        /// 
        /// Runrecipe已经运行的时间
        /// 
        private int _runrecipeElapsedTime = 0;
        /// 
        /// run recipe start time
        /// 
        private DateTime _runRecipeStartTime;
        /// 
        ///  run recipe complete time
        /// 
        private DateTime _runRecipeCompleteTime;
        #endregion
        #region 属性
        /// 
        /// 模块名称
        /// 
        public ModuleName Module { get; private set; }
        /// 
        /// 初始化状态
        /// 
        public bool IsInit {  get { return fsm.State == (int)MetalState.Init; } }
        /// 
        /// 空闲状态
        /// 
        public bool IsIdle { get {  return fsm.State == (int)MetalState.Idle; } }
        /// 
        /// 是否发生错误
        /// 
        public bool IsError { get { return fsm.State == (int)MetalState.Error; } }
        /// 
        /// 是否正在作业
        /// 
        public bool IsBusy {  get { return fsm.State > (int)MetalState.Idle; } }
        /// 
        /// 是否初始化完成
        /// 
        public bool IsInitialized { get { return fsm.State >= (int)MetalState.Initialized; } }
        /// 
        /// 是否禁用
        /// 
        public bool IsDisable { get { return _persistentValue == null || _persistentValue.OperatingMode == DISABLED; } }
        /// 
        /// 自动模式
        /// 
        public bool IsAuto { get { return _persistentValue!=null&&_persistentValue.OperatingMode == AUTO; } }
        /// 
        /// 自动模式
        /// 
        public bool IsManual { get { return _persistentValue != null && _persistentValue.OperatingMode == MANUAL; } }
        /// 
        /// 是否为工程模式
        /// 
        public bool IsEngineering { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == ENGINEERING; } }
        /// 
        /// 是否为产品模式
        /// 
        public bool IsProduction { get { return _persistentValue != null && _persistentValue.RecipeOperatingMode == PRODUCTION; } }
        /// 
        /// WaferHolder信息
        /// 
        public WaferHolderInfo WaferHolderInfo { get { return WaferHolderManager.Instance.GetWaferHolder(Module.ToString()); } }
        /// 
        /// 已完成的RunRecipeCycle次数
        /// 
        public int AchievedCycle { get { return _achievedCycle; } }
        /// 
        /// 当前状态机状态
        /// 
        public int State { get { return fsm.State; } }
        /// 
        /// 当前Metal设置的WaferSize
        /// 
        public int MetalWaferSize { get { return _persistentValue.MetalWaferSize; } }
        /// 
        /// recipe时长
        /// 
        public int RecipeTime { get { return _recipeTime; } }
        /// 
        /// 剩余时间
        /// 
        public override int TimeToReady
        {
            get
            {
                if (IsIdle)
                {
                    return 0;
                }
                switch(fsm.State)
                {
                    case (int)MetalState.RunReciping:                        
                        return Math.Max(_recipeTime - fsm.ElapsedTime/1000, 0);
                    default:
                        return 0 ;
                }
            }
        }
        /// 
        /// 用量
        /// 
        public MetalUsage MetalUsage { get { return MetalUsageManager.Instance.GetMetalUsage(Module.ToString()); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public MetalEntity(ModuleName moduleName)
        {
            this.Module = moduleName;
            WaferManager.Instance.SubscribeLocation(Module, 2);
            InitialFsm();
        }
        /// 
        /// 初始化
        /// 
        /// 
        protected override bool Init()
        {
            InitializeDATA();
            InitializeParameter();
            InitializeRoutine();
            InitializeOperation();
            return true;
        }
        /// 
        /// 初始化参数
        /// 
        private void InitializeParameter()
        {
            _persistentValue = MetalPersistentManager.Instance.GetMetalPersistentValue(Module.ToString());
            if (_persistentValue == null)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Persistent Value Object is not exist");
            }
            _metalItem=MetalItemManager.Instance.GetMetalItem(Module.ToString());
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _compactEmbranceInitializeRoutine = new CompactEmbranceInitializeRoutine(Module.ToString());
            _standardHotInitializeRoutine=new StandardHotInitializeRoutine(Module.ToString());
            _compactEmbranceRunRecipeRoutine=new CompactEmbranceRunRecipeRoutine(Module.ToString());
            _standardHotRunRecipeRoutine=new StandardHotRunRecipeRoutine(Module.ToString());
            _currentShortTestRoutine=new CurrentShortTestRoutine(Module.ToString());
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.InitializeAll", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Initialize); });
            OP.Subscribe($"{Module}.CycleManualProcessRecipe", (cmd, args) => 
            {
                DepRecipe recipe = RecipeFileManager.Instance.LoadGenericityRecipe(args[0].ToString());
                if (recipe == null)
                {
                    LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), $"{args[0]} recipe is null");
                    return false;
                }
                object[] objects = new object[args.Length];
                objects[0] = recipe;
                for(int i = 1; i < args.Length; i++)
                {
                    objects[i] = args[i];
                }
                return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.RunRecipe,objects); 
            });
            OP.Subscribe($"{Module}.CurrentShortTest", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.CurrentShortTest); });
            OP.Subscribe($"{Module}.UpdateMetalUsage", UpdateMetalUsageAction);
            OP.Subscribe($"{Module}.Abort", (cmd, args) => { return CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Abort); });
        }
        /// 
        /// EnterInit
        /// 
        public void EnterInit()
        {
            if ((MetalState)fsm.State != MetalState.Idle) return;
            else
            {
                CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Init);
            }
        }
        /// 初始化状态机
        /// 
        private void InitialFsm()
        {
            fsm = new StateMachine(Module.ToString(), (int)MetalState.Init, 20);
            fsm.EnableRepeatedMsg(true);
            AnyStateTransition(MetalMsg.Error, EnterError, MetalState.Error);
            //Initialize
            AnyStateTransition(MetalMsg.Initialize, InitializeAll, MetalState.Initializing);
            Transition(MetalState.Initializing,FSM_MSG.TIMER,InitializeAllMonitor, MetalState.Initialized);
            //直接进入Idle
            Transition(MetalState.Initialized, FSM_MSG.TIMER, NullFunc, MetalState.Idle);
            //RunRecipe
            Transition(MetalState.Idle, MetalMsg.RunRecipe, RunRecipe, MetalState.RunReciping);
            Transition(MetalState.WaitForRunRecipe, MetalMsg.RunRecipe, RunRecipe, MetalState.RunReciping);
            Transition(MetalState.RunReciping, FSM_MSG.TIMER, RunRecipeMonitor, MetalState.Idle);
            Transition(MetalState.RunReciping, MetalMsg.Abort, AbortRecipe, MetalState.Abort);
            //Current Short Test
            Transition(MetalState.Idle, MetalMsg.CurrentShortTest, CurrentShortTest, MetalState.CurrentShortTesting);
            Transition(MetalState.CurrentShortTesting, FSM_MSG.TIMER, CurrentShortTestMonitor, MetalState.WaitCloseFlow);
            Transition(MetalState.WaitCloseFlow, MetalMsg.CloseFlowValve, CloseFlowValve, MetalState.WaitOpenFlow);
            Transition(MetalState.WaitOpenFlow, MetalMsg.OpenFlowValve, OpenFlowValve, MetalState.WaitForRunRecipe);
            //Enter Init
            Transition(MetalState.Idle, MetalMsg.Init, NullFunc, MetalState.Init);
            EnumLoop.ForEach((item) => { fsm.MapState((int)item, item.ToString()); });
            EnumLoop.ForEach((item) => { fsm.MapMessage((int)item, item.ToString()); });
        }
        /// 
        /// 初始化DATA
        /// 
        private void InitializeDATA()
        {
            InitializeSVID();
            DATA.Subscribe($"{Module}.FsmState", () => ((MetalState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferHolder", () => WaferHolderInfo, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AchievedCycle", () => AchievedCycle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsInit", () => IsInit, SubscriptionAttribute.FLAG.IgnoreSaveDB); 
            DATA.Subscribe($"{Module}.IsIdle", () => IsIdle, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsError", () => IsError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsBusy", () => IsBusy, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.IsDisable", () => IsDisable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CurrentRecipe", () => _currentRecipe != null ? _currentRecipe.Ppid : "", SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MetalUsage", () => MetalUsage, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 初始化SVID
        /// 
        private void InitializeSVID()
        {
            DATA.Subscribe($"{Module}.State", () => ((MetalState)fsm.State).ToString(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.LotID", () => (WaferHolderInfo != null ? WaferHolderInfo.LotId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WSID", () => (WaferHolderInfo != null ? WaferHolderInfo.Id : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.LSAID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.LSBID", () => (WaferHolderInfo != null ? WaferHolderInfo.CrsBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ModuleRecipe", () => (_currentRecipe != null ? _currentRecipe.Ppid : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.SequenceRecipe", () => (WaferHolderInfo != null ? WaferHolderInfo.SequenceId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferAID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferAId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferBID", () => (WaferHolderInfo != null ? WaferHolderInfo.WaferBId : ""), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalTime", () => _recipeTime, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TimeRemain", () => _recipeTime != 0 && _currentRunRecipeRoutine != null ? (_recipeTime - Math.Round((double)_currentRunRecipeRoutine.ElapsedMilliseconds / 1000, 0)) : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.Task", () => WaferHolderInfo != null ? WaferHolderInfo.CurrentControlJobId : "", SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.OperatingMode", () => _persistentValue != null ? _persistentValue.OperatingMode : "None", SubscriptionAttribute.FLAG.IgnoreSaveDB); 
            DATA.Subscribe($"{Module}.TotalUsage", () => MetalUsage != null ? MetalUsage.TotalUsage : 0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalUsage.WarningLimit", () => SC.GetValue("Metal.MetalTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalUsage.FaultLimit", () => SC.GetValue("Metal.MetalTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAUsage",()=> MetalUsage!=null?MetalUsage.AnodeAUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAUsage.WarningLimit", () => SC.GetValue("Metal.AnodeATotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAUsage.FaultLimit", () => SC.GetValue("Metal.AnodeATotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBUsage", () => MetalUsage != null ? MetalUsage.AnodeBUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBUsage.WarningLimit", () => SC.GetValue("Metal.AnodeBTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBUsage.FaultLimit", () => SC.GetValue("Metal.AnodeBTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceAUsage",()=> MetalUsage != null ? MetalUsage.MembranceAUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceAUsage.WarningLimit", () => SC.GetValue("Metal.MembraneATotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceAUsage.FaultLimit", () => SC.GetValue("Metal.MembraneATotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceBUsage", () => MetalUsage != null ? MetalUsage.MembranceBUsage:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceBUsage.WarningLimit", () => SC.GetValue("Metal.MembraneBTotalAmpHoursWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.MembranceBUsage.FaultLimit", () => SC.GetValue("Metal.MembraneBTotalAmpHoursFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalWafers", () => MetalUsage != null ? MetalUsage.TotalWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalWafers.WarningLimit", () => SC.GetValue("Metal.MetalTotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TotalWafers.FaultLimit", () => SC.GetValue("Metal.MetalTotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAWafers",()=> MetalUsage != null ? MetalUsage.AnodeAWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAWafers.WarningLimit", () => SC.GetValue("Metal.AnodeATotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeAWafers.FaultLimit", () => SC.GetValue("Metal.AnodeATotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBWafers", () => MetalUsage != null ? MetalUsage.AnodeBWafers:0, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBWafers.WarningLimit", () => SC.GetValue("Metal.AnodeBTotalWafersWarningLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.AnodeBWafers.FaultLimit", () => SC.GetValue("Metal.AnodeBTotalWafersFaultLimit"), SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 进入错误状态
        /// 
        /// 
        /// 
        private bool EnterError(object[] args)
        {
            if (State == (int)MetalState.RunReciping)
            {
                if (_metalItem.SubType == STRATUS)
                {
                    _standardHotRunRecipeRoutine.Abort();
                }
                else
                {
                    _compactEmbranceRunRecipeRoutine.Abort();
                }
            }
            return true;
        }
        /// 
        /// UpdateMetalUsageAction
        /// 
        /// 
        /// 
        /// 
        private bool UpdateMetalUsageAction(string cmd, object[] args)
        {
            if (args.Length > 2)
            {
                MetalUsageManager.Instance.UpdateMetalUsageByManualOperation(args[0].ToString(), args[1].ToString(), args[2].ToString());
                LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"New {args[1].ToString()} value {args[2].ToString()} was input");
            }
            return true;
        }
        #region Initialize All
        /// 
        /// 初始化
        /// 
        /// 
        /// 
        private bool InitializeAll(object[] param)
        {
            if (fsm.State ==(int)MetalState.Initializing)
            {
                LOG.WriteLog(eEvent.WARN_METAL, Module.ToString(), "state is Initializing,cannot do initialize");
                return false;
            }
            if(!CheckReservoirInitialized())
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Reservoir is not initialized");
                return false;
            }
            if ("Auto".Equals(_persistentValue.OperatingMode))
            {
                if (!CheckReservoirIsAuto())
                {
                    LOG.WriteLog(eEvent.ERR_METAL, Module.ToString(), "Reservoir is not in Auto OperationMode");
                    return false;
                }
            }
            if (_metalItem.SubType==STRATUS)
            {
                return _standardHotInitializeRoutine.Start(_persistentValue) == RState.Running;
            }
            else
            {
                return _compactEmbranceInitializeRoutine.Start(_persistentValue) == RState.Running;
            }
        }
        /// 
        /// 检验Reservoir是否Initialized
        /// 
        /// 
        private bool CheckReservoirInitialized()
        {
            string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
            ReservoirEntity reservoirEntity = Singleton.Instance.GetModule(reservoir);
            if (reservoirEntity != null)
            {
                return reservoirEntity.IsInitialized;
            }
            return false;
        }
        /// 
        /// 检验Reservoir是否Auto
        /// 
        /// 
        private bool CheckReservoirIsAuto()
        {
            string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
            ReservoirsPersistentValue reservoirsPersistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(reservoir);
            if ("Auto".Equals(reservoirsPersistentValue.OperatingMode))
            {
                return true;
            }
            return false;
        }
        /// 
        /// 初始化监控
        /// 
        /// 
        /// 
        private bool InitializeAllMonitor(object[] param)
        {
            RState rsstate= RState.Running;
            if (_metalItem.SubType == STRATUS)
            {
                rsstate = _standardHotInitializeRoutine.Monitor();
            }
            else
            {
                rsstate = _compactEmbranceInitializeRoutine.Monitor() ;
            }
            if(rsstate==RState.End)
            {
                return true;
            }
            else if(rsstate==RState.Failed||rsstate==RState.Timeout)
            {
                PostMsg(MetalMsg.Error);
                return false;
            }
            return false; 
        }
        #endregion
        #region RunRecipe
        /// 
        /// Run Recipe
        /// 
        /// 
        /// 
        private bool RunRecipe(object[] param)
        {
            DepRecipe recipe = param[0] as DepRecipe;
            _recipeSide = param[1].ToString();
            _cycle = (int)param[2];
            _runrecipeElapsedTime = 0;
            bool result = false;
            if (_metalItem.SubType == STRATUS)
            {
                _currentRunRecipeRoutine = _standardHotRunRecipeRoutine;
                result= _standardHotRunRecipeRoutine.Start(recipe,_recipeSide) == RState.Running;
            }
            else
            {
                _currentRunRecipeRoutine = _compactEmbranceRunRecipeRoutine;
                result= _compactEmbranceRunRecipeRoutine.Start(recipe,_recipeSide) == RState.Running;
            }
            if(result)
            {
                if (WaferHolderInfo != null)
                {
                    WaferHolderInfo.MetalModuleName = Module;
                }
                _recipeTime = recipe.CalculateRecipeTotalTime();
                _currentRecipe = recipe;
                if (WaferHolderInfo != null)
                {
                    LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"{WaferHolderInfo?.Id} {string.Join(",", WaferHolderInfo.SchedulerModules)}");
                }
                _runRecipeStartTime = DateTime.Now;
                if (WaferHolderInfo != null && _currentRecipe != null)
                {
                    FaModuleNotifier.Instance.NotifyWaferShuttleRecipeStart(WaferHolderInfo, _currentRecipe.Ppid);
                }
            }
            return result;
        }
        /// 
        /// RunRecipe监控
        /// 
        /// 
        /// 
        private bool RunRecipeMonitor(object[] param)
        {
            RState rsstate = RState.Running;
            if (_metalItem.SubType == STRATUS)
            {
                rsstate = _standardHotRunRecipeRoutine.Monitor();
            }
            else
            {
                rsstate = _compactEmbranceRunRecipeRoutine.Monitor();
            }
            if (Singleton.Instance.IsAutoRunning&&_runrecipeElapsedTime!=TimeToReady)
            {
                _runrecipeElapsedTime = TimeToReady;
                LOG.WriteLog(eEvent.INFO_METAL, Module.ToString(), $"{WaferHolderInfo?.Id} {Module} RunRecipe TimeToReady {TimeToReady}s.");                
            }
            if (rsstate == RState.End)
            {
                _recipeTime = 0;
                if (WaferHolderInfo != null)
                {
                    double anodeAUsage = GetAnodeAUsage();
                    double anodeBUsage = GetAnodeBUsage();
                    MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage);
                    //CMM Usage
                    if(_metalItem.SubType == STRATUS)
                    {
                        string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
                        StandardHotReservoirDevice resDevice = DEVICE.GetDevice(reservoirName);
                        resDevice.SetExportCMMUsage();
                    }                    
                    WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
                }
                _runrecipeElapsedTime = 0;
                
                //记录LotTrack
                _runRecipeCompleteTime = DateTime.Now;
                int timeLength = (int)(_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds;
                if (_metalItem.SubType == STRATUS)
                {
                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
                        _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
                }
                else
                {
                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
                        _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
                }
                if (WaferHolderInfo != null && _currentRecipe != null)
                {
                    FaModuleNotifier.Instance.NotifyWaferShuttleRecipeEnd(WaferHolderInfo, _currentRecipe.Ppid, timeLength);
                }
                    
                return true;
            }
            else if (rsstate == RState.Failed || rsstate == RState.Timeout)
            {
                _recipeTime = 0;
                if (WaferHolderInfo != null)
                {
                    double anodeAUsage = GetAnodeAUsage();
                    double anodeBUsage = GetAnodeBUsage();
                    MetalUsageManager.Instance.UpdateMetalUsage(Module.ToString(), _recipeSide, anodeAUsage, anodeBUsage);
                    //CMMUsage
                    if (_metalItem.SubType == STRATUS)
                    {
                        string reservoirName = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
                        StandardHotReservoirDevice resDevice = DEVICE.GetDevice(reservoirName);
                        resDevice.SetExportCMMUsage();
                    }
                }
                _runrecipeElapsedTime = 0;
                if (WaferHolderInfo != null && _currentRecipe != null)
                {
                    WaferHolderInfo.LastMetalRecipeCompleteTime = DateTime.Now;
                }
                PostMsg(MetalMsg.Error);
                //记录LotTrack
                _runRecipeCompleteTime = DateTime.Now;
                if (_metalItem.SubType == STRATUS)
                {
                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
                        _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
                }
                else
                {
                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                    MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
                        _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
                }
                if (WaferHolderInfo != null && _currentRecipe != null)
                {
                    FaModuleNotifier.Instance.NotifyWaferShuttleRecipeFailed(WaferHolderInfo, _currentRecipe.Ppid);
                }
                return false;
            }
            return false;
        }
        /// 
        /// 获取A面使用的电量
        /// 
        /// 
        private double GetAnodeAUsage()
        {
            if(_metalItem.SubType == STRATUS)
            {
                return Math.Round(_standardHotRunRecipeRoutine.AnodeAUsage,3);
            }
            else
            {
                return Math.Round(_compactEmbranceRunRecipeRoutine.AnodeAUsage,3);
            }
        }
        /// 
        /// 获取B面使用的电量
        /// 
        /// 
        private double GetAnodeBUsage()
        {
            if (_metalItem.SubType == STRATUS)
            {
                return Math.Round(_standardHotRunRecipeRoutine.AnodeBUsage, 3);
            }
            else
            {
                return Math.Round(_compactEmbranceRunRecipeRoutine.AnodeBUsage, 3);
            }
        }
        /// 
        /// Abort Recipe
        /// 
        /// 
        /// 
        public bool AbortRecipe(object[] param)
        {
            _runRecipeCompleteTime = DateTime.Now;
            if (_metalItem.SubType == STRATUS)
            {
                _standardHotRunRecipeRoutine.Abort();
                _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _standardHotRunRecipeRoutine.MetalLotTrackDatas,
                    _standardHotRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
            }
            else
            {
                _compactEmbranceRunRecipeRoutine.Abort();
                _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas.ProcessTime = (_runRecipeCompleteTime - _runRecipeStartTime).TotalSeconds.ToString("F2");
                MetalLotTrackUtil.ExportMetalLotTrack(Module.ToString(), _compactEmbranceRunRecipeRoutine.MetalLotTrackDatas,
                    _compactEmbranceRunRecipeRoutine.MetalLotTrackHeaderDatas, IsAuto, _currentRecipe, _metalItem.SubType);
            }
            
            return true;
        }
        #endregion
        #region Current Short Test
        /// 
        /// Current Short Test
        /// 
        /// 
        /// 
        private bool CurrentShortTest(object[] param)
        {
            return _currentShortTestRoutine.Start() == RState.Running;
        }
        /// 
        /// Current Short test监控
        /// 
        /// 
        /// 
        private bool CurrentShortTestMonitor(object[] param)
        {
            RState rsstate = _currentShortTestRoutine.Monitor();
            if (rsstate == RState.End)
            {
                return true;
            }
            else if (rsstate == RState.Failed || rsstate == RState.Timeout)
            {
                PostMsg(MetalMsg.Error);
                return false;
            }
            return false;
        }
        #endregion
        #region Close Flow Valve
        /// 
        /// 关闭Flow Valve
        /// 
        /// 
        /// 
        private bool CloseFlowValve(object[] param)
        {
            if(_metalItem.SubType==STRATUS)
            {
                StandardHotMetalDevice device = DEVICE.GetDevice(Module.ToString());
                if (device!=null)
                {
                    return device.SwitchToBypass("", null);
                }
                return false;
            }
            else
            {
                CompactMembranMetalDevice device=DEVICE.GetDevice(Module.ToString());
                if(device!=null)
                {
                    string reservoir= ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
                    CompactMembranReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir);
                    if (reservoirDevice != null)
                    {
                        bool result = reservoirDevice.CAByPassOn("", null);
                        if(result)
                        {
                            return device.CellFlowValveOff("", null);
                        }
                    }
                }
                return false;
            }
        }
        #endregion
        #region Open Flow Valve
        /// 
        /// 打开Flow Valve
        /// 
        /// 
        /// 
        private bool OpenFlowValve(object[] param)
        {
            if (_metalItem.SubType == STRATUS)
            {
                StandardHotMetalDevice device = DEVICE.GetDevice(Module.ToString());
                if (device != null)
                {
                    bool result = device.SwitchToFlow("", null);
                    if (result)
                    {
                        return device.PumpOnOperation("",null);
                    }
                }
                return false;
            }
            else
            {
                CompactMembranMetalDevice device = DEVICE.GetDevice(Module.ToString());
                if (device != null)
                {
                    string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module.ToString());
                    CompactMembranReservoirDevice reservoirDevice = DEVICE.GetDevice(reservoir);
                    if (reservoirDevice != null)
                    {
                        bool result = reservoirDevice.CAByPassOff("", null);
                        if (result)
                        {
                            return device.CellFlowValveOn("", null);
                        }
                    }
                }
                return false;
            }
        }
        #endregion
        public bool Check(int msg, out string reason, params object[] args)
        {
            reason = "";
            return true;
        }
        public bool CheckAcked(int msg)
        {
            return true;
        }
        public int Invoke(string function, params object[] args)
        {
            switch (function)
            {
                case "HomeAll":
                    if (IsIdle)
                    {
                        return (int)FSM_MSG.NONE;
                    }
                    if (CheckToPostMessage(eEvent.ERR_METAL, Module.ToString(), (int)MetalMsg.Initialize))
                    {
                        return (int)MetalMsg.Initialize;
                    }
                    else
                    {
                        return (int)FSM_MSG.NONE;
                    }
            }
            return (int)FSM_MSG.NONE;
        }
    }
    public enum MetalMsg
    {
        NONE,
        Error,
        ResumeError,
        Initialize,
        Manual,
        Auto,
        CurrentShortTest,
        CloseFlowValve,
        OpenFlowValve,
        RunRecipe,
        Abort,
        Init
    }
}