using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Event;
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.Beckhoff.ModuleIO;
using MECF.Framework.Common.CommonData;
using MECF.Framework.Common.CommonData.Dryer;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.Persistent.Dryer;
using MECF.Framework.Common.TwinCat;
using MECF.Framework.Common.Utilities;
using CyberX8_Core;
using CyberX8_RT.Devices.Facilities;
using System.Collections.Generic;
using System.Reflection;
using CyberX8_RT.Modules.Dryer;
using CyberX8_RT.Modules;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Dryer
{
    public class DryerDevice : BaseDevice, IDevice
    {
        #region 常量 
        private const string POWER_CONTROL = "PowerControl";
        private const string EXHAUST_PRESSURE = "ExhaustPressure";
        private const string BLOWER_HIGH = "BlowerHigh";
        private const string EXHAUST_LIMIT_DATA = "ExhaustLimitData";
        private const string EXHAUST_PRESSURE_VALUE = "ExhaustPressure";
        private const string COMMON_DATA = "CommonData";
        private const string PERSISTENT_VALUE = "PersistentValue";
        #endregion
        /// 
        /// Dryer操作枚举
        /// 
        private enum DryerCommonOperation
        {
            None,
            ControlPowerOn,
            ControlPowerOff,
            BlowerHigh,
            BlowerLow
        }
        #region 内部变量
        /// 
        /// 公用数据
        /// 
        private DryerCommonData _dryerCommonData;
        /// 
        /// 状态
        /// 
        private RState _status;
        /// 
        /// 当前操作
        /// 
        private DryerCommonOperation _currentOperation;
        /// 
        /// Blower High Routine 
        /// 
        private DryerBlowerHighRoutine _blowerHighRoutine;
        /// 
        /// ByPass
        /// 
        private bool _byPass = false;
        /// 
        /// Facilities
        /// 
        private SystemFacilities _facilities;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 定时器Job
        /// 
        PeriodicJob _periodicJob = null;
        /// 
        /// Dryer 持久性数值对象
        /// 
        private DryerPersistentValue _dryerPersistentValue;
        #endregion
        #region 属性
        /// 
        /// 公用数据对象
        /// 
        public DryerCommonData CommonData { get { return _dryerCommonData; } }
        /// 
        /// 所有io变量是否初始化
        /// 
        public bool IOInitialized { get { return IOVariableDictionaryUtil.AllIoVariableInitialized(eEvent.ERR_DRYER,Module,_variableInitializeDic); } }
        /// 
        /// 状态
        /// 
        public RState Status { get { return _status; } }
        /// 
        /// ByPass
        /// 
        public bool Bypass {  get { return _byPass; } }
        /// 
        /// FacilityCommonLimitData
        /// 
        public CommonLimitData FacilityCommonLimitData { get { return _facilities.GetCommonLimitDataByName(EXHAUST_PRESSURE_VALUE); } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public DryerDevice(string moduleName) : base(moduleName, moduleName,moduleName,moduleName)
        {
            _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
            _dryerCommonData = new DryerCommonData();
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            InitializeRoutine();
            SubscribeData();
            SubscribeValueAction();
            InitializeOperation();
            return true;
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _blowerHighRoutine = new DryerBlowerHighRoutine(Module, this);
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            _dryerPersistentValue = DryerPersistentManager.Instance.GetDryerPersistentValue(Module);
            if (_dryerPersistentValue == null)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, "Persistent Value Object is not exist");
            }
            DATA.Subscribe($"{Module}.{EXHAUST_LIMIT_DATA}", ()=>GetExhaustLimitData(), SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{COMMON_DATA}", () => CommonData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _dryerPersistentValue,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.ExhaustPressure",()=>CommonData.ExhaustPressure, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PowerControl", () => CommonData.PowerControl, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.BlowerHigh", () => CommonData.BlowerHigh, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 获取Exhaust Limit 数据
        /// 
        /// 
        private CommonLimitData GetExhaustLimitData()
        {
            if (_facilities == null)
            {
                _facilities = DEVICE.GetDevice("System.Facilities");
            }
            if (_facilities == null)
            {
                return null;
            }
            return _facilities.GetCommonLimitDataByName(EXHAUST_PRESSURE_VALUE);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            _variableInitializeDic[POWER_CONTROL] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, POWER_CONTROL, UpdateVariableValue);
            _variableInitializeDic[BLOWER_HIGH] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, BLOWER_HIGH, UpdateVariableValue);
            _variableInitializeDic[EXHAUST_PRESSURE] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, EXHAUST_PRESSURE, UpdateVariableValue);
        }
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!CommonData.IsDataInitialized)
            {
                CommonData.IsDataInitialized = true;
            }
            PropertyInfo property = CommonData.GetType().GetProperty(variable);
            if (property != null)
            {               
                property.SetValue(CommonData, value);
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
            if(variable==BLOWER_HIGH)
            {
                if (CommonData.BlowerHigh)
                {
                    DryerAutoOff.Instance.Stop();
                }
                else if(CommonData.PowerControl)
                {
                    DryerAutoOff.Instance.Start();
                }
            }
            else if(variable==POWER_CONTROL)
            {
                if (CommonData.PowerControl)
                {
                    DryerAutoOff.Instance.Start();
                }
                else
                {
                    DryerAutoOff.Instance.Stop();
                }
            }
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.PowerControlOn", PowerControlOnAction);
            OP.Subscribe($"{Module}.PowerControlOff", PowerControlOffAction);
            OP.Subscribe($"{Module}.BlowerHigh",BlowerHighAction);
            OP.Subscribe($"{Module}.BlowerLow", BlowerLowOnAction);
            OP.Subscribe($"{Module}.ByPass", (cmd, args) => { _byPass = (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);
        }
        /// 
        /// 定时器
        /// 
        /// 
        private bool OnTimer()
        {
            if (_status == RState.Running)
            {
                if (_currentOperation != DryerCommonOperation.None)
                {
                    IRoutine routine = GetCurrentRoutine(_currentOperation);
                    if (routine != null)
                    {
                        CheckRoutineState(routine, _currentOperation);
                    }
                    else
                    {
                        EndOperation(RState.End);
                    }
                }
            }
            return true;
        }
        #region Action
        #region Power Control
        /// 
        /// Power Control On操作
        /// 
        private bool PowerControlOnAction(string cmd, object[] args)
        {
            return PowerControlOn();
        }
        /// 
        /// Power Control Off操作
        /// 
        private bool PowerControlOffAction(string cmd, object[] args)
        {
            return PowerControlOff();
        }
        /// 
        /// Power Control On
        /// 
        /// 
        public bool PowerControlOn()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
            bool result= IOModuleManager.Instance.WriteIoValue(ioName, true);
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_DRYER, Module, "Power Control On Success");
            }
            return result;
        }
        /// 
        /// Power Control Off
        /// 
        /// 
        public bool PowerControlOff()
        {
            //检验任一HVD处于High On状态
            if(CheckDryersIsInBlowerHigh())
            {
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
            bool result = IOModuleManager.Instance.WriteIoValue(ioName, false);
            if(result)
            {
                LOG.WriteLog(eEvent.INFO_DRYER, Module, "Power Control Off Success");
            }
            return result;
        }
        /// 
        /// 检验是否Dryers是否有处于BlowerHigh状态
        /// 
        /// 
        public bool CheckDryersIsInBlowerHigh(bool error=true)
        {
            bool dryer1High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer1);
            eEvent eEvent = eEvent.ERR_DRYER;
            if(!error)
            {
                eEvent = eEvent.INFO_DRYER;
            }
            if(dryer1High)
            {
                LOG.WriteLog(eEvent, Module, "Dryer1 is high on");
                return true;
            }
            bool dryer2High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer2);
            if (dryer2High)
            {
                LOG.WriteLog(eEvent, Module, "Dryer2 is high on");
                return true;
            }
            bool dryer3High = CheckDryerModuleIsInBlowerHigh(ModuleName.Dryer3);
            if (dryer3High)
            {
                LOG.WriteLog(eEvent, Module, "Dryer3 is high on");
                return true;
            }
            return false;
        }
        /// 
        /// 检验Dryer模块是否处于Blower High
        /// 
        /// 
        /// 
        private bool CheckDryerModuleIsInBlowerHigh(ModuleName moduleName)
        {
            if (ModuleHelper.IsInstalled(moduleName))
            {
                DryerDevice dryerDevice1 = DEVICE.GetDevice(moduleName.ToString());
                if (dryerDevice1 != null)
                {
                    if (dryerDevice1.CommonData.BlowerHigh)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        #endregion
        #region Blower High
        /// 
        /// Blow High动作
        /// 
        /// 
        /// 
        /// 
        public bool BlowerHighAction(string cmd, object[] args)
        {
            if(JudgeRunningState(DryerCommonOperation.BlowerHigh))
            {
                return false;
            }
            if(CheckDryerModulePowerOff(ModuleHelper.Converter(Module)))
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Power off");
                return false;
            }
            _currentOperation = DryerCommonOperation.BlowerHigh;
            _status = _blowerHighRoutine.Start(_byPass);
            return _status == RState.Running;
        }
        /// 
        /// Blower High On
        /// 
        /// 
        public bool BlowerHighOn()
        {
            if(CheckDryerModulePowerOff(ModuleHelper.Converter(Module)))
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Power off");
                return false;
            }
            CommonLimitData commonLimitData = GetExhaustLimitData();
            if (commonLimitData.IsWarning || commonLimitData.IsError)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, "Exhuast Pressure is Abnormal");
                return false;
            }
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{BLOWER_HIGH}");
            bool result = IOModuleManager.Instance.WriteIoValue(ioName, true);
            if (result)
            {
                LOG.WriteLog(eEvent.INFO_DRYER, Module, "Blower High On Success");
            }
            return result;
        }
        /// 
        /// 检验Dryer模块是否处于PowerOff
        /// 
        /// 
        /// 
        private bool CheckDryerModulePowerOff(ModuleName moduleName)
        {
            if (ModuleHelper.IsInstalled(moduleName))
            {
                DryerDevice dryerDevice1 = DEVICE.GetDevice(moduleName.ToString());
                if (dryerDevice1 != null)
                {
                    if (dryerDevice1.IOInitialized&&!dryerDevice1.CommonData.PowerControl)
                    {
                        return true;
                    }
                }
            }
            return false;
        }
        /// 
        /// 检验是否Dryers是否有处于BlowerHigh状态
        /// 
        /// 
        private bool CheckDryersPowerOff()
        {
            bool dryer1High = CheckDryerModulePowerOff(ModuleName.Dryer1);
            if (dryer1High)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer1 is power off");
                return true;
            }
            bool dryer2High = CheckDryerModulePowerOff(ModuleName.Dryer2);
            if (dryer2High)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer2 is power off");
                return true;
            }
            bool dryer3High = CheckDryerModulePowerOff(ModuleName.Dryer3);
            if (dryer3High)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, "Dryer3 is power off");
                return true;
            }
            return false;
        }
        #endregion
        #region Blower Low
        /// 
        /// Blower Low On Action
        /// 
        /// 
        /// 
        /// 
        private bool BlowerLowOnAction(string cmd, object[] args)
        {
            return BlowerLowOn();
        }
        /// 
        /// Blower Low On
        /// 
        /// 
        public bool BlowerLowOn()
        {
            //High off
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{BLOWER_HIGH}");
            bool result= IOModuleManager.Instance.WriteIoValue(ioName, false);
            if(result)
            {
                string controlPowerOnName= BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{POWER_CONTROL}");
                result= IOModuleManager.Instance.WriteIoValue(controlPowerOnName, true);
            }
            return result;
        }
        #endregion
        /// 
        /// 判定运行状态
        /// 
        /// 
        private bool JudgeRunningState(DryerCommonOperation operation)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} current execute {_currentOperation},cannot {operation}");
                return true;
            }
            return false;
        }
        #endregion
        /// 
        /// 获取当前操作对应的Routine
        /// 
        /// 
        /// 
        private IRoutine GetCurrentRoutine(DryerCommonOperation currentOperation)
        {
            switch (currentOperation)
            {
                case DryerCommonOperation.BlowerHigh:
                    return _blowerHighRoutine;
                default:
                    return null;
            }
        }
        /// 
        /// 检验Routine状态
        /// 
        /// 
        /// 
        private void CheckRoutineState(IRoutine routine, DryerCommonOperation currentOperation)
        {
            RState state = routine.Monitor();
            if (state == RState.End)
            {
                EndOperation(RState.End);
            }
            else if (state == RState.Failed || state == RState.Timeout)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, $"{Module}", $"{currentOperation} error");
                EndOperation(RState.Failed);
            }
        }
        /// 
        /// 结束操作
        /// 
        private void EndOperation(RState state)
        {
            _status = state;
            _currentOperation = DryerCommonOperation.None;
        }
        /// 
        /// DisabledAction
        /// 
        /// 
        /// 
        /// 
        private bool DisabledOperation(string cmd, object[] args)
        {
            string currentOperation = "Disabled";
            DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
            if(dryerEntity == null || _dryerPersistentValue == null) return false;
            if (_dryerPersistentValue.OperatingMode != "Disabled") dryerEntity.EnterInit();
            _dryerPersistentValue.OperatingMode = currentOperation;
            DryerPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ManualAction
        /// 
        /// 
        /// 
        /// 
        private bool ManualOperation(string cmd, object[] args)
        {
            string currentOperation = "Manual";
            DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
            if (dryerEntity == null || _dryerPersistentValue == null) return false;
            if(_dryerPersistentValue.OperatingMode == "Auto" && dryerEntity.IsBusy)
            {
                LOG.WriteLog(eEvent.ERR_DRYER, Module, $"{Module} is Busy, can't change to manual mode");
                return false;
            }
            if (_dryerPersistentValue.OperatingMode != "Manual") dryerEntity.EnterInit();
            _dryerPersistentValue.OperatingMode = currentOperation;
            DryerPersistentManager.Instance.UpdatePersistentValue(Module);
            
            return true;
        }
        /// 
        /// AutoAction
        /// 
        /// 
        /// 
        /// 
        private bool AutoOperation(string cmd, object[] args)
        {
            string currentOperation = "Auto";
            DryerEntity dryerEntity = Singleton.Instance.GetModule(Module);
            if (dryerEntity == null || _dryerPersistentValue == null) return false;
            if (_dryerPersistentValue.OperatingMode != "Auto") dryerEntity.EnterInit();
            _dryerPersistentValue.OperatingMode= currentOperation;
            DryerPersistentManager.Instance.UpdatePersistentValue(Module);
            
            return true;
        }
        /// 
        /// EngineeringModeAction
        /// 
        /// 
        /// 
        /// 
        private bool EngineeringModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Engineering";
            _dryerPersistentValue.RecipeOperatingMode = currentRecipeOperation;
            DryerPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ProductionAction
        /// 
        /// 
        /// 
        /// 
        private bool ProductionModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Production";
            _dryerPersistentValue.RecipeOperatingMode= currentRecipeOperation;
            DryerPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        #region 设备接口
        /// 
        /// 监控
        /// 
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        /// 
        /// 中止
        /// 
        public void Terminate()
        {
            _periodicJob.Stop(false);
        }
        #endregion
    }
}