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.RT.SCCore;
using Aitex.Core.Util;
using MECF.Framework.Common.Algorithm;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData.Prewet;
using MECF.Framework.Common.Device.ResistivityProbe;
using MECF.Framework.Common.Device.Rinse;
using MECF.Framework.Common.Persistent.Prewet;
using MECF.Framework.Common.Persistent.Rinse;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.TwinCat;
using System.Collections.Generic;
using System.Reflection;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Rinse;
using CyberX8_RT.Devices.Resistivity;
using CyberX8_RT.Modules.Prewet;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Rinse
{
    public class RinseDevice : BaseDevice, IDevice
    {
        private enum RinseOperation
        {
            None
        }
        #region 常量 
        private const string WATER_LEVEL="WaterLevel";
        private const string WAFER_HOLDER_CLAMP="WaferHolderClamp";
        private const string N2_VALVE="N2Valve";
        private const string FILL_VALVE="FillValve";
        private const string DRAIN_VALVE="DrainValve";
        private const string WASTE_VALVE="WasteValve";
        private const string RESISTIVITY="Resistivity";
        private const string PERSISTENT_VALUE = "PersistentValue";
        private const string RINSEDATA = "RinseData";
        private const string RINSEITEM = "RinseItem";
        private const string RESISTIVITYVALUE = "Resistivity";
        #endregion
        #region 内部变量
        /// 
        /// 数据
        /// 
        private RinseData _rinseData = new RinseData();
        /// 
        /// Rinse 持久性数值对象
        /// 
        private RinsePersistentValue _rinsePersistentValue;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// ByPass Inter Locks
        /// 
        private bool _bypassInterLocks = false;
        /// 
        /// RinseItem
        /// 
        private RinseItem _rinseItem = new RinseItem();
        /// 
        /// 工艺当前执行小步骤
        /// 
        private string _currentStateMachine = "Init";
        /// 
        /// 工艺当前执行大步骤
        /// 
        private string _currentStatus = "Init";
        /// 
        /// 水阻值
        /// 
        private double _resistivityValue;
        /// 
        /// 水阻计控制器
        /// 
        private ResistivityController _resistivityController;
        #endregion
        #region 属性
        /// 
        /// Rinse数据
        /// 
        public RinseData RinseData { get { return _rinseData; } }
        /// 
        /// 所有io变量是否初始化
        /// 
        public bool IOInitialized { get { return AllIoVariableInitialized(); } }
        /// 
        /// 所有io变量是否初始化
        /// 
        public RinseItem RinseItem { get { return _rinseItem; } }
        /// 
        /// 当前状态机
        /// 
        public string CurrentStateMachine { get { return _currentStateMachine; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public RinseDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
        {
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            SubscribeData();
            SubscribeValueAction();
            InitializeOperation();
            return true;
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            _rinsePersistentValue = RinsePersistentManager.Instance.GetRinsePersistentValue(Module);
            if (_rinsePersistentValue == null)
            {
                LOG.WriteLog(eEvent.ERR_RINSE, Module, "Persistent Value Object is not exist");
            }
            _rinseItem = RinseItemManager.Instance.GetRinseItem(Module);
            _resistivityController = DEVICE.GetDevice(RinseItem.ResistivityID);
            DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _rinsePersistentValue,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{RINSEDATA}", () => _rinseData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CurrentStateMachine", () => _currentStateMachine, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.CurrentStatus", () => _currentStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.Resistivity.ID", () => _resistivityController?.Module, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{RESISTIVITYVALUE}", () => {
                if (_resistivityController != null)
                {
                    string value = _resistivityController.ResisitivityValue;
                    if(double.TryParse(value, out _resistivityValue))
                    {
                        return _resistivityValue;
                    }
                    else
                    {
                        return 0;
                    }
                }
                else
                {
                    return 0;
                }
            }, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaterLevel", () => RinseData.WaterLevel, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.DIFillEnable",()=>RinseData.FillValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.DrainEnable", () => RinseData.DrainValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.N2Enable",()=>RinseData.N2Valve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WaferShuttleClamped",()=>RinseData.WaferHolderClamp, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.WasteEnable", () => RinseData.WasteValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(WATER_LEVEL);
            BeckhoffIoSubscribeUpdateVariable(WASTE_VALVE);
            BeckhoffIoSubscribeUpdateVariable(WAFER_HOLDER_CLAMP);
            BeckhoffIoSubscribeUpdateVariable(N2_VALVE);
            BeckhoffIoSubscribeUpdateVariable(FILL_VALVE);
            BeckhoffIoSubscribeUpdateVariable(DRAIN_VALVE);
        }
        /// 
        /// 初始化Operation
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.ClampValveOn", (cmd, args) => { return WaferHolderClampValveOn(); });
            OP.Subscribe($"{Module}.ClampValveOff", (cmd, args) => { return WaferHolderClampValveOff(); });
            OP.Subscribe($"{Module}.N2ValveOn", (cmd, args) => { return N2ValveOn(); });
            OP.Subscribe($"{Module}.N2ValveOff", (cmd, args) => { return N2ValveOff(); });
            OP.Subscribe($"{Module}.FillValveOn", (cmd, args) => { return FillValveOn(); });
            OP.Subscribe($"{Module}.FillValveOff", (cmd, args) => { return FillValveOff(); });
            OP.Subscribe($"{Module}.DrainValveOn", (cmd, args) => { return DrainValveOn(); });
            OP.Subscribe($"{Module}.DrainValveOff", (cmd, args) => { return DrainValveOff(); });
            OP.Subscribe($"{Module}.WasteValveOn", (cmd, args) => { return WasteValveOff() ;});
            OP.Subscribe($"{Module}.WasteValveOff", (cmd, args) => { return WasteValveOn() ;});
            OP.Subscribe($"{Module}.ByPassInterLocks", (cms, args) => { _bypassInterLocks = (bool)(args[0]); return true; });
            OP.Subscribe($"{Module}.DisabledAction", DisabledOperation);
            OP.Subscribe($"{Module}.ManualAction", ManualOperation);
            OP.Subscribe($"{Module}.AutoAction", AutoOperation);
            OP.Subscribe($"{Module}.EngineeringModeAction", EngineeringModeOperation);
            OP.Subscribe($"{Module}.ProductionModeAction", ProductionModeOperation);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!RinseData.IsDataInitialized)
            {
                RinseData.IsDataInitialized = true;
            }
            PropertyInfo property = RinseData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(RinseData, value);
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
        }
        /// 
        /// 是否所有IO变量初始化完成
        /// 
        /// 
        private bool AllIoVariableInitialized()
        {
            foreach (string item in _variableInitializeDic.Keys)
            {
                if (!_variableInitializeDic[item])
                {
                    LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{item} is not initialized");
                    return false;
                }
            }
            return true;
        }
        #region Operation
        /// 
        /// DisabledAction
        /// 
        /// 
        /// 
        /// 
        private bool DisabledOperation(string cmd, object[] args)
        {
            string currentOperation = "Disabled";
            RinseEntity rinseEntity = Singleton.Instance.GetModule(Module);
            if (rinseEntity != null && _rinsePersistentValue != null && _rinsePersistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _rinsePersistentValue.OperatingMode;
                if (rinseEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RINSE, Module, $"{Module} is Busy, can't switch to Disabled mode");
                    return false;
                }
                rinseEntity.EnterInit();
                _rinsePersistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RINSE, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            RinsePersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ManualAction
        /// 
        /// 
        /// 
        /// 
        private bool ManualOperation(string cmd, object[] args)
        {
            string currentOperation = "Manual";
            RinseEntity rinseEntity = Singleton.Instance.GetModule(Module);
            if (rinseEntity != null && _rinsePersistentValue != null && _rinsePersistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _rinsePersistentValue.OperatingMode;
                if (rinseEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RINSE, Module, $"{Module} is Busy, can't switch to Manual mode");
                    return false;
                }
                rinseEntity.EnterInit();
                _rinsePersistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RINSE, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            RinsePersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// AutoAction
        /// 
        /// 
        /// 
        /// 
        private bool AutoOperation(string cmd, object[] args)
        {
            string currentOperation = "Auto";
            RinseEntity rinseEntity = Singleton.Instance.GetModule(Module);
            if (rinseEntity != null && _rinsePersistentValue != null && _rinsePersistentValue.OperatingMode != currentOperation)
            {
                string preOperation = _rinsePersistentValue.OperatingMode;
                if (rinseEntity.IsBusy)
                {
                    LOG.WriteLog(eEvent.ERR_RINSE, Module, $"{Module} is Busy, can't switch to Auto mode");
                    return false;
                }
                rinseEntity.EnterInit();
                _rinsePersistentValue.OperatingMode = currentOperation;
                LOG.WriteLog(eEvent.INFO_RINSE, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            }
            RinsePersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// EngineeringModeAction
        /// 
        /// 
        /// 
        /// 
        private bool EngineeringModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Engineering";
            _rinsePersistentValue.RecipeOperatingMode = currentRecipeOperation;
            RinsePersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ProductionAction
        /// 
        /// 
        /// 
        /// 
        private bool ProductionModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Production";
            _rinsePersistentValue.RecipeOperatingMode = currentRecipeOperation;
            RinsePersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        #endregion
        /// 
        /// 更新当前工艺小步骤
        /// 
        /// 
        public void UpdateStateMachine(string tmp)
        {
            _currentStateMachine = tmp;
        }
        /// 
        /// 更新当前工艺大步骤
        /// 
        /// 
        public void UpdateStatus(string tmp)
        {
            _currentStatus = tmp;
        }
        #region Wafer Holder Clamp Valve 
        /// 
        /// Wafer Holder Clamp Valve On
        /// 
        /// 
        public bool WaferHolderClampValveOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WAFER_HOLDER_CLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Wafer Holder Clamp Valve Off
        /// 
        /// 
        public bool WaferHolderClampValveOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WAFER_HOLDER_CLAMP}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region N2 Valve 
        /// 
        /// N2 Valve On
        /// 
        /// 
        public bool N2ValveOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{N2_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// N2 Valve Off
        /// 
        /// 
        public bool N2ValveOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{N2_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region Fill Valve 
        /// 
        /// Fill Valve On
        /// 
        /// 
        public bool FillValveOn()
        {
            if(!_bypassInterLocks)
            {
                //Clamp Status必须为Clamped
                if(!_rinseData.WaferHolderClamp)
                {
                    LOG.WriteLog(eEvent.ERR_RINSE, Module, "Clamp Status is not Clamped");
                    return false;
                }
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{FILL_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Fill Valve Off
        /// 
        /// 
        public bool FillValveOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{FILL_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region Drain Valve 
        /// 
        /// Drain Valve On
        /// 
        /// 
        public bool DrainValveOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DRAIN_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Drain Valve Off
        /// 
        /// 
        public bool DrainValveOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{DRAIN_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        #region Waste Valve 
        /// 
        /// Waste Valve On
        /// 
        /// 
        public bool WasteValveOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WASTE_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Waste Valve Off(等价于Metal Valve On)
        /// 
        /// 
        public bool WasteValveOff()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{WASTE_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        #endregion
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
        }
    }
}