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.Persistent.Prewet;
using MECF.Framework.Common.TwinCat;
using CyberX8_Core;
using System;
using System.Collections.Generic;
using System.Reflection;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Prewet;
using CyberX8_RT.Modules.Metal;
using MECF.Framework.Common.Persistent.Temperature;
using MECF.Framework.Common.IOCore;
namespace CyberX8_RT.Devices.Prewet
{
    public class PrewetDevice : BaseDevice, IDevice
    {
        private enum PrewetOperation
        {
            None,
            PumpEnable,
            PumpDisable
        }
        #region 常量 
        private const string PUMP_VALVE = "PumpValve";
        private const string PUMP_ENABLE = "PumpEnable";
        private const string PUMP_SPEED = "PumpSpeed";
        private const string PUMP_STAUS = "PumpStatus";
        private const string PUMP_CURRENT = "PumpCurrent";
        private const string PUMP_FLOW = "PumpFlow";
        private const string PUMP_PRESSURE = "PumpPressure";
        private const string PUMP_DATA = "PumpData";
        private const string PERSISTENT_VALUE = "PersistentValue";
        #endregion
        #region 内部变量
        /// 
        /// 数据
        /// 
        private PrewetPumpData _prewetPumpData=new PrewetPumpData();
        /// 
        /// pdi控制中的p
        /// 
        private double _pumpKp;
        /// 
        /// pdi控制中的i
        /// 
        private double _pumpKi;
        /// 
        /// pdi控制中的d
        /// 
        private double _pumpKd;
        /// 
        /// 操作当前状态
        /// 
        private RState _status;
        /// 
        /// 当前操作
        /// 
        private PrewetOperation _currentOperation;
        /// 
        /// Prewet 持久性数值对象
        /// 
        private PrewetPersistentValue _prewetPersistentValue;
        /// 
        /// Pump Enable routine
        /// 
        private PrewetPumpEnableRoutine _prewetPumpEnableRoutine;
        /// 
        /// Pump Disable routine
        /// 
        private PrewetPumpDisableRoutine _prewetPumpDisableRoutine;
        /// 
        /// 上一次Pump速度
        /// 
        private short _lastPumpSpeed;
        /// 
        /// 变量是否初始化字典
        /// 
        private Dictionary _variableInitializeDic = new Dictionary();
        /// 
        /// 定时器Job
        /// 
        PeriodicJob _periodicJob = null;
        /// 
        /// Run recipe total time
        /// 
        public int _runRecipeTotalTime;
        #endregion
        #region 属性
        /// 
        /// Pump 数据
        /// 
        public PrewetPumpData PrewetPumpData { get { return _prewetPumpData; } }
        /// 
        /// 操作当前状态
        /// 
        public RState Status { get { return _status; } }
        /// 
        /// 所有io变量是否初始化
        /// 
        public bool IOInitialized { get { return AllIoVariableInitialized(); } }
        /// 
        /// Last Pump Speed
        /// 
        public short LastPumpSpeed { get { return _lastPumpSpeed; } }
        /// 是否启动调速
        /// 
        public bool IsStartAutoSpeed { get; set; }
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        /// 
        public PrewetDevice(string moduleName) : base(moduleName, moduleName,moduleName,moduleName)
        {
            _prewetPumpData = new PrewetPumpData();
            _prewetPumpData.PumpPressureData = new MECF.Framework.Common.CommonData.CommonLimitData();
            _prewetPumpData.PumpFlowData = new MECF.Framework.Common.CommonData.CommonLimitData();
            _periodicJob = new PeriodicJob(100, OnTimer, $"{Module}.OnTimer", true);
        }
        /// 
        /// 初始化
        /// 
        /// 
        public bool Initialize()
        {
            InitializeParameter();
            InitializeRoutine();
            SubscribeData();
            SubscribeValueAction();
            InitializeOperation();
            return true;
        }
        /// 
        /// 初始化参数
        /// 
        private void InitializeParameter()
        {
            _prewetPersistentValue = PrewetPersistentManager.Instance.GetPrewetPersistentValue(Module);
            if (_prewetPersistentValue != null)
            {
                _lastPumpSpeed = _prewetPersistentValue.Speed;
            }
            else
            {
                LOG.WriteLog(eEvent.ERR_PREWET, Module, "Persistent Value Object is not exist");
            }
        }
        /// 
        /// 初始化Routine
        /// 
        private void InitializeRoutine()
        {
            _prewetPumpEnableRoutine = new PrewetPumpEnableRoutine(Module, this, _prewetPersistentValue);
            _prewetPumpDisableRoutine = new PrewetPumpDisableRoutine(Module, this, _prewetPersistentValue);
        }
        /// 
        /// 订阅数据
        /// 
        private void SubscribeData()
        {
            DATA.Subscribe($"{Module}.{PERSISTENT_VALUE}", () => _prewetPersistentValue, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.{PUMP_DATA}", () => PrewetPumpData, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.OfTotalTime", () => _runRecipeTotalTime ,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpStatus", () => PrewetPumpData.PumpStatus, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpCurrent",()=>PrewetPumpData.PumpCurrent,SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpSpeed", () => _lastPumpSpeed, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpEnable", () => PrewetPumpData.PumpEnable, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpValve", () => PrewetPumpData.PumpValve, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpFlow", () => PrewetPumpData.PumpFlowData.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpFlow.MinWarning", () => PrewetPumpData.PumpFlowData.MinWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpFlow.MaxWarning", () => PrewetPumpData.PumpFlowData.MaxWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpFlow.MinError", () => PrewetPumpData.PumpFlowData.MinError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpFlow.MaxError", () => PrewetPumpData.PumpFlowData.MaxError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpPressure", () => PrewetPumpData.PumpPressureData.Value, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpPressure.MinWarning", () => PrewetPumpData.PumpPressureData.MinWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpPressure.MaxWarning", () => PrewetPumpData.PumpPressureData.MaxWarning, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpPressure.MinError", () => PrewetPumpData.PumpPressureData.MinError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.PumpPressure.MaxError", () => PrewetPumpData.PumpPressureData.MaxError, SubscriptionAttribute.FLAG.IgnoreSaveDB);
            DATA.Subscribe($"{Module}.TargetPressure", () => PrewetPumpData.PressureTarget, SubscriptionAttribute.FLAG.IgnoreSaveDB);
        }
        /// 
        /// 订阅变量数值发生变化
        /// 
        private void SubscribeValueAction()
        {
            BeckhoffIoSubscribeUpdateVariable( PUMP_VALVE);
            BeckhoffIoSubscribeUpdateVariable( PUMP_ENABLE);
            BeckhoffIoSubscribeUpdateVariable( PUMP_STAUS);
            BeckhoffIoSubscribeUpdateVariable( PUMP_CURRENT);
            BeckhoffIoSubscribeUpdateVariable( PUMP_PRESSURE);
            BeckhoffIoSubscribeUpdateVariable( PUMP_FLOW);
        }
        /// 
        /// 订阅IO变量
        /// 
        /// 
        private void BeckhoffIoSubscribeUpdateVariable(string variable)
        {
            _variableInitializeDic[variable] = false;
            IOModuleManager.Instance.SubscribeModuleVariable(Module, variable, UpdateVariableValue);
        }
        /// 
        /// 更新变量数值
        /// 
        /// 
        /// 
        private void UpdateVariableValue(string variable, object value)
        {
            if (!PrewetPumpData.IsDataInitialized)
            {
                PrewetPumpData.IsDataInitialized = true;
                PrewetPumpData.PumpModel = "Manual";
            }
            PropertyInfo property = PrewetPumpData.GetType().GetProperty(variable);
            if (property != null)
            {
                property.SetValue(PrewetPumpData, value);
            }
            if (_variableInitializeDic.ContainsKey(variable) && !_variableInitializeDic[variable])
            {
                _variableInitializeDic[variable] = true;
            }
            switch (variable)
            {
                case PUMP_STAUS:
                    string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
                    PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
                    break;
                case PUMP_FLOW:
                    if (double.TryParse(value.ToString(), out var flow))
                    {
                        PrewetPumpData.PumpFlowData.Value = flow;
                    }
                    break;
                case PUMP_PRESSURE:
                    if(double.TryParse(value.ToString(),out var pressure))
                    {
                        PrewetPumpData.PumpPressureData.Value = pressure;
                    }
                    break;
            }
        }
        /// 
        /// 是否所有IO变量初始化完成
        /// 
        /// 
        private bool AllIoVariableInitialized()
        {
            foreach (string item in _variableInitializeDic.Keys)
            {
                if (!_variableInitializeDic[item])
                {
                    LOG.WriteLog(eEvent.ERR_PREWET, Module, $"{item} is not initialized");
                    return false;
                }
            }
            return true;
        }
        /// 
        /// 初始化操作
        /// 
        private void InitializeOperation()
        {
            OP.Subscribe($"{Module}.PumpValveOn", PumpValveOnOperation);
            OP.Subscribe($"{Module}.PumpValveOff", PumpValveOffOperation);
            OP.Subscribe($"{Module}.PumpEnable", PumpEnableOperation);
            OP.Subscribe($"{Module}.PumpDisable", PumpDisableOperation);
            OP.Subscribe($"{Module}.PumpSpeedManual", PumpSpeedManualOperation);
            OP.Subscribe($"{Module}.PumpSpeedAuto", PumpSpeedAutoOperation);
            OP.Subscribe($"{Module}.PumpSpeedKeyDown", PumpSpeedKeyDownOperation);
            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()
        {
            PrewetPumpData.PumpFlowData.MinError = SC.GetValue($"Prewet.PumpFlow.Error_Min");
            PrewetPumpData.PumpFlowData.MinWarning = SC.GetValue($"Prewet.PumpFlow.Warning_Min");
            PrewetPumpData.PumpFlowData.MaxError = SC.GetValue($"Prewet.PumpFlow.Error_Max");
            PrewetPumpData.PumpFlowData.MaxWarning = SC.GetValue($"Prewet.PumpFlow.Warning_Max");
            PrewetPumpData.PumpPressureData.MinError = SC.GetValue($"Prewet.PumpPressure.Error_Min");
            PrewetPumpData.PumpPressureData.MinWarning = SC.GetValue($"Prewet.PumpPressure.Warning_Min");
            PrewetPumpData.PumpPressureData.MaxError = SC.GetValue($"Prewet.PumpPressure.Error_Max");
            PrewetPumpData.PumpPressureData.MaxWarning = SC.GetValue($"Prewet.PumpPressure.Warning_Max");
            PrewetPumpData.PressureTarget = SC.GetValue($"Prewet.PressureTarget");
            if (_status == RState.Running)
            {
                IRoutine routine = GetCurrentRoutine();
                if (routine != null)
                {
                    RState rsState = routine.Monitor();
                    if (rsState == RState.Failed || rsState == RState.Timeout)
                    {
                        _status = RState.Failed;
                        _currentOperation = PrewetOperation.None;
                        LOG.WriteLog(eEvent.ERR_LINMOT, Module.ToString(), $"{_currentOperation} error");
                        IsStartAutoSpeed = false;
                    }
                    else if (rsState == RState.End)
                    {
                        if (_currentOperation == PrewetOperation.PumpEnable)
                        {
                            IsStartAutoSpeed = true;
                        }
                        else
                        {
                            IsStartAutoSpeed = false;
                        }
                        _status = RState.End;
                        _currentOperation = PrewetOperation.None;                        
                    }
                }
            }
            if (IsStartAutoSpeed)
            {
                AdjustPumpSpeed();
            }
            return true;
        }
        /// 
        /// 调速
        /// 
        public void AdjustPumpSpeed()
        {
            //Speed Auto模式同时pump enbled,根据kdi调整泵速
            if (PrewetPumpData.PumpSpeedAuto && PrewetPumpData.PumpEnable)
            {
                _pumpKp = SC.GetValue($"Prewet.PumpKp");
                _pumpKd = SC.GetValue($"Prewet.PumpKd");
                _pumpKi = SC.GetValue($"Prewet.PumpKi");
                double limit = SC.GetValue("Prewet.PrewetTargetLimit");
                short speed = PdiAlgorithm.Instance.CalculateSpeed(_pumpKp, _pumpKi, _pumpKd, PrewetPumpData.PressureTarget,
                    PrewetPumpData.PumpPressureData.Value, _lastPumpSpeed,limit);
                if (Math.Abs(speed - _lastPumpSpeed) >= 1)
                {
                    _lastPumpSpeed = speed;
                    PumpSpeed(speed);
                }
            }
            else
            {
                IsStartAutoSpeed = false;
            }
        }
        /// 
        /// 当前Routine;
        /// 
        /// 
        private IRoutine GetCurrentRoutine()
        {
            switch (_currentOperation)
            {
                case PrewetOperation.PumpEnable:
                    return _prewetPumpEnableRoutine;
                case PrewetOperation.PumpDisable:
                    return _prewetPumpDisableRoutine;
                default:
                    return null;
            }
        }
        #region Operation
        /// 
        /// DisabledAction
        /// 
        /// 
        /// 
        /// 
        private bool DisabledOperation(string cmd, object[] args)
        {
            string currentOperation = "Disabled";
            PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
            if (prewetEntity == null || _prewetPersistentValue == null) return false;
            if (_prewetPersistentValue.OperatingMode != "Disabled") prewetEntity.EnterInit();
            _prewetPersistentValue.OperatingMode = currentOperation;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ManualAction
        /// 
        /// 
        /// 
        /// 
        private bool ManualOperation(string cmd, object[] args)
        {
            string currentOperation = "Manual";
            PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
            if (prewetEntity == null || _prewetPersistentValue == null) return false;
            if (_prewetPersistentValue.OperatingMode == "Auto" && prewetEntity.IsBusy)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, Module, $"{Module} is Busy, can't change to manual mode");
                return false;
            }
            if (_prewetPersistentValue.OperatingMode != "Manual") prewetEntity.EnterInit();
            _prewetPersistentValue.OperatingMode = currentOperation;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// AutoAction
        /// 
        /// 
        /// 
        /// 
        private bool AutoOperation(string cmd, object[] args)
        {
            string currentOperation = "Auto";
            PrewetEntity prewetEntity = Singleton.Instance.GetModule(Module);
            if (prewetEntity == null || _prewetPersistentValue == null) return false;
            if (_prewetPersistentValue.OperatingMode != "Auto") prewetEntity.EnterInit();
            _prewetPersistentValue.OperatingMode = currentOperation;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// EngineeringModeAction
        /// 
        /// 
        /// 
        /// 
        private bool EngineeringModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Engineering";
            _prewetPersistentValue.RecipeOperatingMode=currentRecipeOperation;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// ProductionAction
        /// 
        /// 
        /// 
        /// 
        private bool ProductionModeOperation(string cmd, object[] args)
        {
            string currentRecipeOperation = "Production";
            _prewetPersistentValue.RecipeOperatingMode = currentRecipeOperation;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            return true;
        }
        /// 
        /// Pump Valve On
        /// 
        /// 
        /// 
        /// 
        public bool PumpValveOnOperation(string cmd, object[] param)
        {
            return PumpValveOpen();
        }
        /// 
        /// Pump Valve Off
        /// 
        /// 
        /// 
        /// 
        public bool PumpValveOffOperation(string cmd, object[] param)
        {
            return PumpValveClose();
        }
        /// 
        /// Pump Valve Open
        /// 
        /// 
        public bool PumpValveOpen()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_VALVE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Pump Valve Close
        /// 
        /// 
        public bool PumpValveClose()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_VALVE}");
            bool result= IOModuleManager.Instance.WriteIoValue(ioName, false);
            if(result && PrewetPumpData.PumpEnable)
            {
                PumpDisable();
            }
            return result;
        }
        /// 
        /// Pump Enable操作
        /// 
        /// 
        /// 
        /// 
        public bool PumpEnableOperation(string cmd, object[] param)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump enable");
                return false;
            }
            _status = _prewetPumpEnableRoutine.Start();
            _currentOperation = PrewetOperation.PumpEnable;
            return _status==RState.Running;
        }
        ///  
        /// pump disable 操作
        /// 
        /// 
        /// 
        /// 
        public bool PumpDisableOperation(string cmd, object[] param)
        {
            if (_status == RState.Running)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, Module.ToString(), $"{Module} current execute {_currentOperation},cannot Pump disable");
                return false;
            }
            _status = _prewetPumpDisableRoutine.Start();
            _currentOperation = PrewetOperation.PumpDisable;
            return _status == RState.Running;
            //return PumpDisable();
        }
        /// 
        /// Pump enable
        /// 
        /// 
        public bool PumpEnable()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_ENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, true);
        }
        /// 
        /// Pump disable
        /// 
        /// 
        public bool PumpDisable()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_ENABLE}");
            return IOModuleManager.Instance.WriteIoValue(ioName, false);
        }
        /// 
        /// 写入Pump速度
        /// 
        /// 
        /// 
        public bool PumpSpeed(short speed=0)
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{Module}.{PUMP_SPEED}");
            return IOModuleManager.Instance.WriteIoValue(ioName, speed==0?_lastPumpSpeed:speed);
        }
        /// 
        /// Pump Speed手动模式
        /// 
        /// 
        /// 
        /// 
        public bool PumpSpeedManualOperation(string cmd, object[] param)
        {
            PrewetPumpData.PumpSpeedAuto = false;
            PrewetPumpData.PumpModel = "Manual";
            string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
            PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
            return true;
        }
        /// 
        /// Pump Speed自动模式
        /// 
        /// 
        /// 
        /// 
        public bool PumpSpeedAutoOperation(string cmd, object[] param)
        {
            PrewetPumpData.PumpSpeedAuto = true;
            PrewetPumpData.PumpModel = "Auto";
            string statusContent = PrewetPumpData.PumpStatus ? "On" : "Off";
            PrewetPumpData.PumpStatusContent = $"{PrewetPumpData.PumpModel}: {statusContent}";
            return true;
        }
        /// 
        /// Pump Speed回车操作
        /// 
        /// 
        /// 
        /// 
        public bool PumpSpeedKeyDownOperation(string cmd, object[] param)
        {
            if (PrewetPumpData.PumpSpeedAuto)
            {
                LOG.WriteLog(eEvent.ERR_PREWET, Module, "Pump speed is auto,cannot change speed");
                return false;
            }
            short speed=(short)param[0];
            bool result = PumpSpeed(speed);
            if(result)
            {
                _prewetPersistentValue.Speed = speed;
                _lastPumpSpeed = speed;
                PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            }
            return true;
        }
        /// 
        /// 中止当前Routine
        /// 
        public void AbortCurrentRoutine()
        {
            if (_status == RState.Running)
            {
                IRoutine routine = GetCurrentRoutine();
                if (routine != null)
                {
                    routine.Abort();
                    _currentOperation = PrewetOperation.None;
                }
            }
        }
        #endregion
        #region 设备接口
        /// 
        /// 监控
        /// 
        public void Monitor()
        {
        }
        public void Reset()
        {
        }
        public void Terminate()
        {
            _prewetPersistentValue.Speed = _lastPumpSpeed;
            PrewetPersistentManager.Instance.UpdatePersistentValue(Module);
            _periodicJob.Stop(false);
        }
        #endregion
    }
}