using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.Util;
using MECF.Framework.Common.CommonData.Reservoir;
using MECF.Framework.Common.IOCore;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.TwinCat;
using MECF.Framework.Common.Utilities;
using PunkHPX8_RT.Modules;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
namespace PunkHPX8_RT.Devices.Reservoir
{
    public class ReservoirDevice : BaseDevice, IDevice
    {
        #region 常量
        private const string AUTO = "Auto";
        private const string MANUAL = "Manual";
        private const string DISABLE = "Disable";
        private const string CA_PUMP_RUNNING="CaPumpRunning";
        private const string AN_TOWER_HIGH="AnTowerHigh";
        private const string AN_TOWER_LOW="AnTowerLow";
        private const string CA_LEVEL="CaLevel";
        private const string CA_WATER_LEVEL="CaWaterLevel";
        private const string AN_FLOW="AnFlow";
        private const string AN_PUMP_ENABLE="AnPumpEnable";
        private const string AN_PUMP_SPEED="AnPumpSpeed";
        private const string CA_FLOW="CaFlow";
        private const string CA_PUMP_ENABLE="CaPumpEnable";
        private const string CA_PUMP_SPEED="CaPumpSpeed";
        private const string RETURN_VALVE_OPENING="ReturnValveOpening";
        private const string RETURN_VALVE="ReturnValve";
        private const string RETURN_VALVE_PERCENT="ReturnValvePercent";
        private const string CA_DI_REPLEN="CaDiReplen";
        private const string AN_DI_REPLEN="AnDiReplen";
        private const string SAMPLE_OUT="SampleOut";
        private const string DEGAS_ENABLE="DegasEnable";
        private const string HED_FLOW="HedFlow";
        private const string HED_FLOW_ENABLE="HedFlowEnable";
        private const string PH_FLOW_VALVE="PhFlowValve";
        private const string PH_VALUE="PhValue";
        #endregion
        #region 内部变量
        /// 
        /// Prewet 持久性数值对象
        /// 
        private ReservoirsPersistentValue _persistentValue;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 数据
        /// 
        private ReservoirData _reservoirData = new ReservoirData();
        /// 
        /// 定时器
        /// 
        private PeriodicJob _periodicJob;
        #endregion
        #region 属性
        /// 
        /// 操作模式
        /// 
        public string OperationMode { get { return _persistentValue.OperatingMode; } }
        /// 
        /// 工程模式
        /// 
        public string EngineerMode { get { return _persistentValue.RecipeOperatingMode; } }
        /// 
        /// 是否自动
        /// 
        public bool IsAuto { get { return _persistentValue.OperatingMode == AUTO; } }
        /// 
        /// 数据
        /// 
        public ReservoirData ReservoirData { get { return _reservoirData; } }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public ReservoirDevice(string moduleName) : base(moduleName, moduleName, moduleName, moduleName)
        {
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            InitializeParameter();
            InitializeRoutine();
            SubscribeData();
            InitializeOperation();
            SubscribeValueAction();
            _periodicJob = new PeriodicJob(200, OnTimer, $"{Module}.Timer", true, true);
            return true;
        }
        /// 
        /// 初始化参数
        /// 
        private void InitializeParameter()
        {
            _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(Module.ToString());
            if (_persistentValue == null)
            {
                LOG.WriteLog(eEvent.ERR_RESERVOIR, Module.ToString(), "Persistent Value Object is not exist");
            }
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            DATA.Subscribe($"{Module}.ReservoirData", () => _reservoirData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 初始化Operation
        /// 
        private void InitializeOperation()
        {
            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);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        protected virtual void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_RUNNING);
            BeckhoffIoSubscribeUpdateVariable(AN_TOWER_HIGH);
            BeckhoffIoSubscribeUpdateVariable(AN_TOWER_LOW);
            BeckhoffIoSubscribeUpdateVariable(CA_LEVEL);
            BeckhoffIoSubscribeUpdateVariable(CA_WATER_LEVEL);
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_ENABLE);
            BeckhoffIoSubscribeUpdateVariable(CA_PUMP_SPEED);
            BeckhoffIoSubscribeUpdateVariable(CA_DI_REPLEN);
            BeckhoffIoSubscribeUpdateVariable(RETURN_VALVE);
            BeckhoffIoSubscribeUpdateVariable(RETURN_VALVE_OPENING);
            BeckhoffIoSubscribeUpdateVariable(RETURN_VALVE_PERCENT);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!_reservoirData.IsDataInitialized)
            {
                _reservoirData.IsDataInitialized = true;
            }
            PropertyInfo property = _reservoirData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(_reservoirData, value);
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
        }
        /// 
        /// 定时器
        /// 
        /// 
        protected virtual bool OnTimer()
        {
            return true;
        }
        #region Mode switch
        /// 
        /// DisabledAction
        /// 
        /// 
        /// 
        /// 
        private bool DisabledOperation(string cmd, object[] args)
        {
            string currentOperation = "Disabled";
            string preOperation = _persistentValue.OperatingMode;
            _persistentValue.OperatingMode = currentOperation;
            LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ManualAction
        /// 
        /// 
        /// 
        /// 
        private bool ManualOperation(string cmd, object[] args)
        {
            string currentOperation = "Manual";
            string preOperation = _persistentValue.OperatingMode;
            
            _persistentValue.OperatingMode = currentOperation;
            LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// AutoAction
        /// 
        /// 
        /// 
        /// 
        private bool AutoOperation(string cmd, object[] args)
        {
            string currentOperation = "Auto";
            string preOperation = _persistentValue.OperatingMode;
            _persistentValue.OperatingMode = currentOperation;
            LOG.WriteLog(eEvent.INFO_RESERVOIR, Module, $"Operating mode is switched from {preOperation} to {currentOperation}");
            
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// EngineeringModeAction
        /// 
        /// 
        /// 
        /// 
        private bool EngineeringModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Engineering";
            if (_persistentValue != null)
            {
                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ProductionAction
        /// 
        /// 
        /// 
        /// 
        private bool ProductionModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Production";
            if (_persistentValue != null)
            {
                _persistentValue.RecipeOperatingMode = currentRecipeOperation;
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        #endregion
        /// 
        /// 监控
        /// 
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
        }
    }
}