using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.Routine;
using Aitex.Core.UI.Control;
using Aitex.Core.Util;
using MECF.Framework.Common.Beckhoff.IOAxis;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.CommonData.Metal;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using CyberX8_RT.Devices.Prewet;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using MECF.Framework.Common.ToolLayout;
using CyberX8_RT.Devices.Reservoir;
using MECF.Framework.Common.Layout;
using Aitex.Core.RT.SCCore;
using System.Diagnostics;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Metal
{
    public class CompactMembranMetalDevice : MetalCellDevice
    {
        private enum ANCellStatus
        {
            Unknow,
            Filling,
            Emptying,
            Full,
            Empty
        }
        private enum ANCellOperation
        {
            None,
            Fill,
            Drain
        }
        #region 常量 
        private const string SIDE_A = "SideA";
        private const string SIDE_B = "SideB";
        private const string AN_A_PINENABLE="ANAPinEnable";
        private const string AN_B_PINENABLE = "ANBPinEnable";
        private const string AN_A_POUTENABLE = "ANAPoutEnable";
        private const string AN_B_POUTENABLE = "ANBPoutEnable";
        private const string CELL_FLOW = "CellFlow";
        private const string WH_CLAMP = "WHClamp";
        private const string WH_UNCLAMP = "WHUnclamp";
        private const string CELL_FLOW_VALVE = "CellFlowValve";
        private const string COUNTER_VALUE = "CounterValue";
        private const string COUNTER_START = "Start";
        private const string COUNTER_STOP = "Stop";
        private const string COUNTER_RESET = "Reset";
        private const string AN_A_CELL_FLOW = "ANACellFlow";
        private const string AN_B_CELL_FLOW = "ANBCellFlow";
        #endregion
        #region 内部变量
        /// 
        /// 设备数据
        /// 
        private CompactMembranMetalDeviceData _metalDeviceData =new CompactMembranMetalDeviceData();
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 阳极A面cellFlow
        /// 
        private CounterFlowData _anACellFlow = new CounterFlowData();
        /// 
        /// 阳极B面cellFlow
        /// 
        private CounterFlowData _anBCellFlow = new CounterFlowData();
        /// 
        /// Counter字典
        /// 
        private Dictionary _nameCounterFlowData = new Dictionary();
        /// 
        /// 当前阳极A面操作
        /// 
        private ANCellOperation _currentANACellOperation;
        /// 
        /// 当前阳机B面操作
        /// 
        private ANCellOperation _currentANBCellOperation;
        /// 
        /// AN Fill Routine
        /// 
        private CompactMembranFillRoutine _anANACellFillRoutine;
        /// 
        /// 阳机B面Fill Routine
        /// 
        private CompactMembranFillRoutine _anANBCellFillRoutine;
        /// 
        /// 阳极A面流量总数值 
        /// 
        private double _anATotalFillFlow = 0;
        /// 
        /// 阳极B面流量总数值 
        /// 
        private double _anBTotalFillFlow = 0;
        /// 
        /// 阳极A面Drain时间
        /// 
        private DateTime _anADrainTime = DateTime.Now;
        /// 
        /// 阳极B面Drain时间
        /// 
        private DateTime _anBDrainTime = DateTime.Now;
        /// 
        /// Flow Valve计时
        /// 
        private Stopwatch _flowValveStopWatch = new Stopwatch();
        #endregion
        #region 属性
        /// 
        /// 设备数据
        /// 
        public CompactMembranMetalDeviceData MetalDeviceData { get { return _metalDeviceData; } }
        /// 
        /// 阳极A面CellFlow
        /// 
        public CounterFlowData ANACellFlow { get { return _anACellFlow; } }
        /// 
        /// 阳极B面CellFlow
        /// 
        public CounterFlowData ANBCellFlow { get { return _anBCellFlow; } }
        /// 
        /// Flow Valve稳定状态
        /// 
        public bool FlowValveStable { get { return _metalDeviceData.CellFlowValve && _flowValveStopWatch.ElapsedMilliseconds >= 3000; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public CompactMembranMetalDevice(string moduleName) : base(moduleName)
        {
        }
        
        /// 
        /// 初始化
        /// 
        /// 
        public override bool Initialize()
        {
            base.Initialize();
            InitializeRoutine();
            SubscribeValueAction();
            SubscribeData();
            return true;
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _anANACellFillRoutine = new CompactMembranFillRoutine(Module,"A");
            _anANBCellFillRoutine = new CompactMembranFillRoutine(Module,"B");
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            DATA.Subscribe($"{Module}.MetalData", () => _metalDeviceData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.SideAFlow",()=>ANACellFlow.CounterValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.SideAFlowStatus", () => ANACellFlow.Status, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.SideBFlow", () => ANBCellFlow.CounterValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.SideBFlowStatus",()=>ANBCellFlow.Status, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CellFlow",()=>MetalDeviceData.CellFlow, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANBPinEnable",()=>_metalDeviceData.ANBPinEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANAPinEnable", () => _metalDeviceData.ANAPinEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANAPoutEnable", () => _metalDeviceData.ANAPoutEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ANBPoutEnable", () => _metalDeviceData.ANBPoutEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CellFlowEnable", () => _metalDeviceData.CellFlowValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferShuttleClamped", () => _metalDeviceData.WHClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferShuttleUnclamped", () => _metalDeviceData.WHUnclamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(AN_A_PINENABLE);
            BeckhoffIoSubscribeUpdateVariable(AN_B_PINENABLE);
            BeckhoffIoSubscribeUpdateVariable(AN_A_POUTENABLE);
            BeckhoffIoSubscribeUpdateVariable(AN_B_POUTENABLE);
            BeckhoffIoSubscribeUpdateVariable(CELL_FLOW);
            BeckhoffIoSubscribeUpdateVariable(WH_CLAMP);
            BeckhoffIoSubscribeUpdateVariable(WH_UNCLAMP);
            BeckhoffIoSubscribeUpdateVariable(CELL_FLOW_VALVE);
            BeckhoffCounterSubscribeUpdateVariable(AN_A_CELL_FLOW,ANACellFlow);
            BeckhoffCounter anACellFlowCounter = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_A_CELL_FLOW}");
            if(anACellFlowCounter!=null)
            {
                ANACellFlow.Period = anACellFlowCounter.Period;
            }
            BeckhoffCounterSubscribeUpdateVariable(AN_B_CELL_FLOW,ANBCellFlow);
            BeckhoffCounter anBCellFlowCounter = BeckhoffCounterManager.Instance.GetBeckhoffCounter($"{Module}.{AN_B_CELL_FLOW}");
            if (anACellFlowCounter != null)
            {
                ANBCellFlow.Period = anBCellFlowCounter.Period;
            }
        }
        /// 
        /// 订阅Operation
        /// 
        protected override void InitializeOperation()
        {
            base.InitializeOperation();
            OP.Subscribe($"{Module}.ANAFillOn",AnSideAFillOn);
            OP.Subscribe($"{Module}.ANAFillOff", AnSideAFillOff);
            OP.Subscribe($"{Module}.ANBFillOn", AnSideBFillOn);
            OP.Subscribe($"{Module}.ANBFillOff", AnSideBFillOff);
            OP.Subscribe($"{Module}.ANADrainOn", AnSideADrainOn);
            OP.Subscribe($"{Module}.ANADrainOff", AnSideADrainOff);
            OP.Subscribe($"{Module}.ANBDrainOn", AnSideBDrainOn);
            OP.Subscribe($"{Module}.ANBDrainOff", AnSideBDrainOff);
            OP.Subscribe($"{Module}.WHClampOn", WHClampOn);
            OP.Subscribe($"{Module}.WHClampOff", WHClampOff);
            OP.Subscribe($"{Module}.WHUnclampOn", WHUnClampOn);
            OP.Subscribe($"{Module}.WHUnclampOff", WHUnClampOff);
            OP.Subscribe($"{Module}.CellFlowValveOn", CellFlowValveOn);
            OP.Subscribe($"{Module}.CellFlowValveOff", CellFlowValveOff);
            OP.Subscribe($"{Module}.WaferHolderClampOn", WaferHolderClampOn);
            OP.Subscribe($"{Module}.WaferHolderUnclampOn", WaferHolderUnclampOn);
            OP.Subscribe($"{Module}.WaferHolderDisconnect", WaferHolderDisConnect);
            OP.Subscribe($"{Module}.A.Fill", ANSideAFillOperation);
            OP.Subscribe($"{Module}.B.Fill", ANSideBFillOperation);
            OP.Subscribe($"{Module}.A.Stop", ANSideAStopOperation);
            OP.Subscribe($"{Module}.B.Stop", ANSideBStopOperation);
            OP.Subscribe($"{Module}.A.Drain", ANSideADrainOperation);
            OP.Subscribe($"{Module}.B.Drain", ANSideBDrainOperation);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!_metalDeviceData.IsDataInitialized)
            {
                _metalDeviceData.IsDataInitialized = true;
            }
            PropertyInfo property = _metalDeviceData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(_metalDeviceData, value);
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
            if (variable == CELL_FLOW_VALVE)
            {
                bool bValue = (bool)value;
                if (bValue)
                {
                    _flowValveStopWatch.Restart();
                }
            }
        }
        /// 
        /// 订阅Counter变量
        /// 
        /// 
        private void BeckhoffCounterSubscribeUpdateVariable(string variable,CounterFlowData counterFlowData)
        {
            _nameCounterFlowData[$"{Module}.{variable}"] = counterFlowData;
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_VALUE, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_START, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_STOP, UpdateCounterVariableValue);
            BeckhoffCounterManager.Instance.SubscribeModuleVariable($"{Module}.{variable}", COUNTER_RESET, UpdateCounterVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateCounterVariableValue(string variable, object value)
        {
            string[] strAry = variable.Split('.');
            string lastVariable = strAry[strAry.Length - 1];
            PropertyInfo property = null;
            string key = variable.Replace($".{lastVariable}", "");
            if(_nameCounterFlowData.ContainsKey(key))
            {
                CounterFlowData counterFlowData = _nameCounterFlowData[key];
                if (counterFlowData != null)
                {
                    property = counterFlowData.GetType().GetProperty(lastVariable);
                    if (property != null)
                    {
                        property.SetValue(counterFlowData, value);
                    }
                }
            }
        }
        #region Fill
        /// 
        /// AN A面Fill On
        /// 
        /// 
        /// 
        /// 
        public bool AnSideAFillOn(string cmd, object[] param)
        {
            string ioName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_PINENABLE}");
            string countName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_CELL_FLOW}");
            bool result= BeckhoffCounterManager.Instance.StartCounter(countName);
            if (result)
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, true);
            }
            else
            {
                return false;
            }
        }
        /// 
        /// AN A面Fill Off
        /// 
        /// 
        /// 
        /// 
        public bool AnSideAFillOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_PINENABLE}");
            string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_CELL_FLOW}");
            bool result = BeckhoffCounterManager.Instance.StopCounter(countName);
            if(result)
            {
                result= BeckhoffCounterManager.Instance.ResetCounter(countName,0);
                if(result)
                {
                    return IOModuleManager.Instance.WriteIoValue(ioName, false);
                }
            }
            return false;
        }
        /// 
        /// AN B面Fill On
        /// 
        /// 
        /// 
        /// 
        public bool AnSideBFillOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_PINENABLE}");
            string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_CELL_FLOW}");
            bool result = BeckhoffCounterManager.Instance.StartCounter(countName);
            if (result)
            {
                return IOModuleManager.Instance.WriteIoValue(ioName, true);
            }
            else
            {
                return false;
            }
        }
        /// 
        /// AN B面Fill Off
        /// 
        /// 
        /// 
        /// 
        public bool AnSideBFillOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_PINENABLE}");
            string countName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_CELL_FLOW}");
            bool result = BeckhoffCounterManager.Instance.StopCounter(countName);
            if (result)
            {
                result = BeckhoffCounterManager.Instance.ResetCounter(countName, 0);
                if (result)
                {
                    return IOModuleManager.Instance.WriteIoValue(ioName, false);
                }
            }
            return false;
        }
        #endregion
        #region Drain
        /// 
        /// AN A面Drain On
        /// 
        /// 
        /// 
        /// 
        private bool AnSideADrainOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_POUTENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// AN A面Drain Off
        /// 
        /// 
        /// 
        /// 
        public bool AnSideADrainOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_A_POUTENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// AN B面Drain On
        /// 
        /// 
        /// 
        /// 
        private bool AnSideBDrainOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_POUTENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// AN A面Drain Off
        /// 
        /// 
        /// 
        /// 
        public bool AnSideBDrainOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{AN_B_POUTENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region WH Clamp
        /// 
        /// WH Clamp On
        /// 
        /// 
        /// 
        /// 
        private bool WHClampOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// WH Clamp Off
        /// 
        /// 
        /// 
        /// 
        private bool WHClampOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// WH UnClamp On
        /// 
        /// 
        /// 
        /// 
        private bool WHUnClampOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// WH UnClamp Off
        /// 
        /// 
        /// 
        /// 
        private bool WHUnClampOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// Wafer Holder Clamp On
        /// 
        /// 
        /// 
        /// 
        public bool WaferHolderClampOn(string cmd, object[] param)
        {
            string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
            bool result = IOModuleManager.Instance.WriteIoValue(unclampIOName, false);
            if(result)
            {
                string clampIOName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
                return IOModuleManager.Instance.WriteIoValue(clampIOName, true);
            }
            return false;
        }
        /// 
        /// Wafer Holder Clamp On
        /// 
        /// 
        /// 
        /// 
        public bool WaferHolderUnclampOn(string cmd, object[] param)
        {
            string clampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
            bool result = IOModuleManager.Instance.WriteIoValue(clampIOName, false);
            if (result)
            {
                string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
                return IOModuleManager.Instance.WriteIoValue(unclampIOName, true);
            }
            return false;
        }
        /// 
        /// Wafer Holder Disconnect
        /// 
        /// 
        /// 
        /// 
        public bool WaferHolderDisConnect(string cmd, object[] param)
        {
            string clampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_CLAMP}");
            bool result = IOModuleManager.Instance.WriteIoValue(clampIOName, false);
            if (result)
            {
                string unclampIOName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WH_UNCLAMP}");
                return IOModuleManager.Instance.WriteIoValue(unclampIOName, false);
            }
            return false;
        }
        #endregion
        #region Cell Flow Valve
        /// 
        /// Cell Flow On
        /// 
        /// 
        /// 
        /// 
        public bool CellFlowValveOn(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_FLOW_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Cell Flow Off
        /// 
        /// 
        /// 
        /// 
        public bool CellFlowValveOff(string cmd, object[] param)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{CELL_FLOW_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region AN Fill
        /// 
        /// 阳极A面Fill
        /// 
        /// 
        /// 
        /// 
        private bool ANSideAFillOperation(string cmd, object[] objects)
        {
            if(_currentANACellOperation!=ANCellOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANACellOperation},cannot execute AN Side A Fill");
                return false;
            }
            bool result = _anANACellFillRoutine.Start() == RState.Running;
            if (result)
            {
                _currentANACellOperation = ANCellOperation.Fill;
            }
            return result;
        }
        /// 
        /// 阳极B面Fill
        /// 
        /// 
        /// 
        /// 
        private bool ANSideBFillOperation(string cmd, object[] objects)
        {
            if (_currentANBCellOperation != ANCellOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANBCellOperation},cannot execute AN Side B Fill");
                return false;
            }
            bool result = _anANBCellFillRoutine.Start() == RState.Running;
            if (result)
            {
                _currentANBCellOperation = ANCellOperation.Fill;
            }
            return result;
        }
        #endregion
        #region AN Drain
        /// 
        /// 阳极A面Drain
        /// 
        /// 
        /// 
        /// 
        private bool ANSideADrainOperation(string cmd, object[] objects)
        {
            if (_currentANACellOperation != ANCellOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANACellOperation},cannot execute AN Side A Drain");
                return false;
            }
            bool result = true;
            CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
            if(CheckOtherMetalDeviceDrainStatus(reservoirDevice,"A"))
            {
                return false;
            }
            if (reservoirDevice != null && reservoirDevice.ReservoirData.ANADrainPump == 0)
            {
                result = reservoirDevice.AnADrainPumpOn("", null);
            }
            if (result)
            {
                result = AnSideADrainOn("", null);
                if (result)
                {
                    ANACellFlow.Status = ANCellStatus.Emptying.ToString();
                    _anATotalFillFlow = 0;
                    _anADrainTime=DateTime.Now;
                }
                else
                {
                    reservoirDevice.AnADrainPump(0);
                }
            }
            return result;
        }
        /// 
        /// 其他Metal Drain是否打开
        /// 
        /// 
        /// 
        /// 
        private bool CheckOtherMetalDeviceDrainStatus(CompactMembranReservoirDevice reservoirDevice,string side)
        {
            if(reservoirDevice==null)
            {
                return false;
            }
            ReservoirItem reservoirItem = ReservoirItemManager.Instance.GetReservoirItem(reservoirDevice.Module);
            if(reservoirItem!=null)
            {
                foreach(var item in reservoirItem.MetalCells)
                {
                    if(item.ModuleName!=Module)
                    {
                        CompactMembranMetalDevice metalDevice = DEVICE.GetDevice(item.ModuleName);
                        if(metalDevice!=null)
                        {
                            if(side=="A"&&metalDevice.MetalDeviceData.ANAPoutEnable)
                            {
                                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{item.ModuleName} A Drain is on");
                                return true;
                            }
                            if (side == "B" && metalDevice.MetalDeviceData.ANBPoutEnable)
                            {
                                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{item.ModuleName} B Drain is on");
                                return true;
                            }
                        }
                    }
                }
            }
            return false;
        }
        /// 
        /// 阳极A面Drain
        /// 
        /// 
        /// 
        /// 
        private bool ANSideBDrainOperation(string cmd, object[] objects)
        {
            if (_currentANBCellOperation != ANCellOperation.None)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"{Module} current is {_currentANBCellOperation},cannot execute AN Side A Drain");
                return false;
            }
            bool result = true;
            CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
            if (CheckOtherMetalDeviceDrainStatus(reservoirDevice, "B"))
            {
                return false;
            }
            if(reservoirDevice!=null&&reservoirDevice.ReservoirData.ANBDrainPump==0)
            {
                result= reservoirDevice.AnBDrainPumpOn("", null);
            }
            if (result)
            {
                result = AnSideBDrainOn("", null);
                if (result)
                {
                    ANBCellFlow.Status = ANCellStatus.Emptying.ToString();
                    _anBTotalFillFlow = 0;
                    _anBDrainTime=DateTime.Now;
                }
                else
                {
                    reservoirDevice.AnBDrainPump(0);
                }
            }
            return result;
        }
        #endregion
        #region AN Stop
        /// 
        /// 阳面A停止 
        /// 
        /// 
        /// 
        /// 
        private bool ANSideAStopOperation(string cmd, object[] objs)
        {
            CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
            if (reservoirDevice != null)
            {
                if (reservoirDevice.ReservoirData.ANPump != 0)
                {
                    reservoirDevice.AnPump(0);
                }
                if (reservoirDevice.ReservoirData.ANADrainPump != 0)
                {
                    reservoirDevice.AnADrainPump(0);
                }
            }
            if (MetalDeviceData.ANAPinEnable)
            {
                AnSideAFillOff("", null);
            }
            if (MetalDeviceData.ANAPoutEnable)
            {
                AnSideADrainOff("", null);
            }            
            ANACellFlow.Status = ANCellStatus.Unknow.ToString();
            _anATotalFillFlow = 0;
            return true;
        }
        /// 
        /// 阳面A停止 
        /// 
        /// 
        /// 
        /// 
        private bool ANSideBStopOperation(string cmd, object[] objs)
        {
            CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
            if (reservoirDevice != null)
            {
                if (reservoirDevice.ReservoirData.ANPump != 0)
                {
                    reservoirDevice.AnPump(0);
                }
                if(reservoirDevice.ReservoirData.ANBDrainPump!=0)
                {
                    reservoirDevice.AnBDrainPump(0);
                }
            }
            if(MetalDeviceData.ANBPinEnable)
            {
                AnSideBFillOff("", null);
            }
            if(MetalDeviceData.ANBPoutEnable)
            {
                AnSideBDrainOff("", null);
            }
            ANBCellFlow.Status = ANCellStatus.Unknow.ToString();
            _anBTotalFillFlow = 0;
            return true;
        }
        #endregion
        #region Timer定时器
        /// 
        /// 定时器
        /// 
        /// 
        public override bool OnTimer(int interval)
        {
            if (_currentANACellOperation == ANCellOperation.Fill)
            {
                SideFillRoutineMonitor(_anANACellFillRoutine, "A", ANACellFlow, ref _currentANACellOperation);
            }
            if (_currentANBCellOperation == ANCellOperation.Fill)
            {
                SideFillRoutineMonitor(_anANBCellFillRoutine, "B", ANBCellFlow, ref _currentANBCellOperation);
            }
            //正在Filing
            if (ANACellFlow.Status == ANCellStatus.Filling.ToString())
            {
                JudgeFillFull(ANACellFlow,interval,ref _anATotalFillFlow);
            }
            if (ANBCellFlow.Status == ANCellStatus.Filling.ToString())
            {
                JudgeFillFull(ANBCellFlow,interval,ref _anBTotalFillFlow);
            }
            if (ANACellFlow.Status == ANCellStatus.Emptying.ToString())
            {
                JudgeDrainEmpty("A");
            }
            if (ANBCellFlow.Status == ANCellStatus.Emptying.ToString())
            {
                JudgeDrainEmpty("B");
            }
            return true;
        }
        /// 
        /// 单面Fill Routine监控
        /// 
        /// 
        /// 
        /// 
        private void SideFillRoutineMonitor(IRoutine routine, string side,CounterFlowData counterFlowData, ref ANCellOperation operation)
        {
            RState state = routine.Monitor();
            if (state == RState.Failed || state == RState.Timeout)
            {
                CloseReservoirPumpAndMetalFill(side);
                operation = ANCellOperation.None;
            }
            else if (state == RState.End)
            {
                counterFlowData.Status = ANCellStatus.Filling.ToString();
                operation = ANCellOperation.None;
            }
        }
        /// 
        /// 判定是否fill Full
        /// 
        private void JudgeFillFull(CounterFlowData counterFlowData,int interval,ref double totalFillFlow)
        {
            double anodeFillVolume = SC.GetValue($"Metal.AnodeFillVolume");
            totalFillFlow += counterFlowData.CounterValue / 60 * ((double)interval / 1000);
            if (totalFillFlow >= anodeFillVolume)
            {
                counterFlowData.Status = "Full";
            }
        }
        /// 
        /// 判定是否Drain Empty
        /// 
        /// 
        private void JudgeDrainEmpty(string side)
        {
            if (side == "A")
            {
                JudgeSideADrain(ANACellFlow, _anADrainTime);
                if(ANACellFlow.Status==ANCellStatus.Empty.ToString())
                {
                    CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
                    if (reservoirDevice != null)
                    {
                        reservoirDevice.AnADrainPump(0);
                    }
                    AnSideADrainOff("", null);
                }
            }
            else
            {
                JudgeSideADrain(ANBCellFlow, _anBDrainTime);
                if (ANBCellFlow.Status == ANCellStatus.Empty.ToString())
                {
                    CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
                    if (reservoirDevice != null)
                    {
                        reservoirDevice.AnBDrainPump(0);
                    }
                    AnSideBDrainOff("", null);
                }
            }
        }
        /// 
        /// 判定单面Drain的情况
        /// 
        /// 
        /// 
        private void JudgeSideADrain(CounterFlowData counterFlowData, DateTime drainDateTime)
        {
            double anodeDrainTime = SC.GetValue("Metal.AnodeDrainTime");
            if (DateTime.Now.Subtract(drainDateTime).TotalMilliseconds >= anodeDrainTime * 1000)
            {
                counterFlowData.Status = ANCellStatus.Empty.ToString();
            }
        }
        /// 
        /// 关闭Reservoir Pump和Metal Fill
        /// 
        private void CloseReservoirPumpAndMetalFill(string side)
        {
            CompactMembranReservoirDevice reservoirDevice = GetReservoirDevice();
            if (reservoirDevice != null)
            {
                reservoirDevice.AnPump(0);
                if (side == "A")
                {
                    AnSideAFillOff("", null);
                }
                else
                {
                    AnSideBDrainOff("", null);
                }
            }
        }
        /// 
        /// 获取Reservoir设备
        /// 
        /// 
        private CompactMembranReservoirDevice GetReservoirDevice()
        {
            string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module);
            return DEVICE.GetDevice(reservoir);
        }
        #endregion
        /// 
        /// Enter Disabled Operation
        /// 
        /// 
        public void EnterDisabledOperation()
        {
            ANSideAStopOperation("", null);
            ANSideBStopOperation("", null);
            if (_metalDeviceData.CellFlowValve)
            {
                CellFlowValveOff("", null);
            }            
        }
        #region 设备接口
        public override void Monitor()
        {
        }
        public override void Reset()
        {
        }
        public override void Terminate()
        {
        }
        #endregion
    }
}