using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using CyberX8_Core;
using CyberX8_RT.Devices.Dose;
using CyberX8_RT.Modules;
using CyberX8_RT.Modules.Reservoir;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.IOCore;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.ProcessCell;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.TwinCat;
using System;
using System.Reflection;
using System.Windows;
using static CyberX8_RT.Devices.Reservoir.DosingSystemHelper;
namespace CyberX8_RT.Devices.Reservoir
{
    public class CrossDoseHelper
    {
        #region 常量        
        public enum CrossDoseOperation
        {
            None,
            ManualDosing,
            AutoDosing,
        }
        /// 
        /// 补液体积(固定10mL)
        /// 
        private const double DOSING_VOLUME = 10;
        #endregion
        #region 内部变量
        /// 
        /// ModuleName
        /// 
        private string _moduleName;
        /// 
        /// ANTransferPumpOnRoutine
        /// 
        private ANTransferPumpOnRoutine _anTransferPumpOnRoutine;
        /// 
        /// CrossDoseResetRoutine
        /// 
        private CrossDoseResetRoutine _crossDoseResetRoutine;
        /// 
        /// ReservoirsPersistentValue
        /// 
        private ReservoirsPersistentValue _persistentValue;
        /// 
        /// CompactMembranReservoirDevice 
        /// 
        private CompactMembranReservoirDevice _cmReservoirDevice;
        /// 
        /// CrossDoseVolume
        /// 
        private double _crossDoseVolume;
        /// 
        /// 当前CrossDose模式
        /// 
        private CrossDoseOperation _currentCrossDoseOperation;
        /// 
        /// Reservoir Usage
        /// 
        private ReservoirUsage _reservoirUsage;
        private bool _flag;
        #endregion
        #region 属性
        /// 
        /// 当前Dose模式
        /// 
        public CrossDoseOperation CurrentDoseOperation{ get {return _currentCrossDoseOperation; } }
        /// 
        /// CrossDose当前的RState
        /// 
        public RState CrossDoseState { get { return _anTransferPumpOnRoutine.CurrentState; } }
        /// 
        /// ResetRoutine当前的RState
        /// 
        public RState ResetState { get { return _crossDoseResetRoutine.CurrentState; } }
        #endregion
        public CrossDoseHelper(string moduleName) 
        {
            _moduleName = moduleName;   
            _anTransferPumpOnRoutine = new ANTransferPumpOnRoutine(_moduleName);
            _crossDoseResetRoutine = new CrossDoseResetRoutine(_moduleName);
            _persistentValue = ReservoirsPersistentManager.Instance.GetReservoirsPersistentValue(_moduleName);
            _cmReservoirDevice = DEVICE.GetDevice($"{_moduleName}");
            _currentCrossDoseOperation = CrossDoseOperation.None;
        }
        #region Operation
        /// 
        /// 开始Dosing
        /// 
        /// 
        public bool StartDosing(double crossDoseVolume)
        {
            _crossDoseVolume = crossDoseVolume;
            return _anTransferPumpOnRoutine.Start(crossDoseVolume) == RState.Running;
        }
        /// 
        /// 停止Dosing
        /// 
        /// 
        public bool HaltDosing()
        {
            _anTransferPumpOnRoutine.Abort();
            EnterError();
            return true;
        }
        /// 
        /// CrossDosing监控
        /// 
        public void CrossDoseStatusMonitor()
        {
            RState result = _anTransferPumpOnRoutine.Monitor();                                        
            //监控Pump
            if (result == RState.Failed || result == RState.Timeout)
            {
                EnterError();   
                LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Open AN Transfer Pump failed");
                _cmReservoirDevice.InitializeCrossDose(false);
            }
        }
        /// 
        /// 自动CrossDose监控
        /// 
        public void AutoCrossDoseMonitor(bool isInitialized)
        {
            if (!isInitialized)
            {               
                if (!_flag)
                {
                    LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Please initialize Cross Dose");
                    _flag = true;
                }                
                return;
            }
            _flag = false;
            if (_cmReservoirDevice.Recipe != null && (_cmReservoirDevice.Recipe.CurrentBased || _cmReservoirDevice.Recipe.TimeBased))
            {
                //非AutoDosing模式下进入AutoDosing模式,并记录开始数据
                if (_currentCrossDoseOperation != CrossDoseOperation.AutoDosing)
                {
                    LOG.WriteLog(eEvent.INFO_RESERVOIR, _moduleName, $"Timing of AutoCrossDose has started now");
                    RecordStartData();
                    SetAutoDoseOperation();
                }
                else
                {
                    //AutoDosing模式下,若上一次Dosing完成则再次记录数据
                    if (_persistentValue.AutoCrossDoseStartTime == DateTime.MinValue && _persistentValue.AutoCrossDoseStartAmpHour == 0)
                    {
                        LOG.WriteLog(eEvent.INFO_RESERVOIR, _moduleName, $"Timing of AutoCrossDose has started again now");
                        RecordStartData();
                    }
                }               
            }
            else
            {
                ResetDoseOperation();   
            }
            //AutoDosing监控
            if (CrossDoseState != RState.Running && _currentCrossDoseOperation == CrossDoseOperation.AutoDosing && AutoDosingMonitor())
            {
                StartDosing(DOSING_VOLUME);
            }
        }
        /// 
        /// CrossDoseOperation状态监控
        /// 
        public bool CrossDoseOperationMonitor()
        {
            if (_currentCrossDoseOperation == CrossDoseOperation.ManualDosing && CrossDoseState != RState.Running)
            {
                _currentCrossDoseOperation = CrossDoseOperation.None;
            }
            if (_currentCrossDoseOperation == CrossDoseOperation.AutoDosing)
            {
                _currentCrossDoseOperation = CrossDoseOperation.None;
            }
            return true;
        }
        /// 
        /// 自动补液触发时机判断
        /// 
        /// 
        private bool AutoDosingMonitor()
        {
            ResRecipe recipe = _cmReservoirDevice.Recipe;
            bool result = false;
            double targetVolume = 0;
            double currentDosingAmpHour = 0;
            _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);           
            //当前电量
            if (_reservoirUsage != null) currentDosingAmpHour = _reservoirUsage.TotalUsage;
            //累计电量(Ah)
            double deltAmpHour = currentDosingAmpHour - _persistentValue.AutoCrossDoseStartAmpHour;
            //累计时间(Day)
            double deltDay = DateTime.Now.Subtract(_persistentValue.AutoCrossDoseStartTime).TotalDays;
            if (recipe.CurrentBased)
            {
                //基于电量补液
                targetVolume = deltAmpHour * recipe.CrossDoseCurrentRate;
                _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
                if (targetVolume >= DOSING_VOLUME)
                {
                    result = true;
                }
            }
            else if (recipe.TimeBased)
            {
                //基于时间则开始补液
                targetVolume = deltDay * recipe.CrossDoseTimeRate;
                _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
                if (targetVolume >= DOSING_VOLUME)
                {
                    result = true;
                }
            }
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
            return result;
        }
        /// 
        /// 设置手动Dose模式
        /// 
        public void SetManualDoseOperation()
        {
            _currentCrossDoseOperation = CrossDoseOperation.ManualDosing;
        }
        /// 
        /// 设置自动Dose模式
        /// 
        public void SetAutoDoseOperation()
        {
            _currentCrossDoseOperation = CrossDoseOperation.AutoDosing;           
        }
        /// 
        /// 重置Dose模式
        /// 
        public void ResetDoseOperation()
        {
            _currentCrossDoseOperation = CrossDoseOperation.None;
        }
        /// 
        /// EnterError
        /// 
        private bool EnterError()
        {
            string ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{_moduleName}.TransferPumpExecute");
            bool result = IOModuleManager.Instance.WriteIoValue(ioName, false);
            if (!result)
            {
                return false;
            }
            ioName = BeckhoffModuleIOManager.Instance.GetIoNameByInnerModuleName($"{_moduleName}.TransferPumpEnable");
            result = IOModuleManager.Instance.WriteIoValue(ioName, false);
            if (!result)
            {
                return false;
            }
            if (!_cmReservoirDevice.CrossDoseOff("", null))
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, $"Close CrossDose Valve failed");
                return false;
            }
            return true;
        }
        /// 
        /// 记录AutoCrossDose开始时的时间和电量
        /// 
        private void RecordStartData()
        {
            _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
            _persistentValue.AutoCrossDoseStartTime = DateTime.Now;
            if (_reservoirUsage != null) _persistentValue.AutoCrossDoseStartAmpHour = _reservoirUsage.TotalUsage;
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
        }
        /// 
        /// 设置PumpFactor
        /// 
        public void SetPumpfactor(double targetPumpFactor)
        {
            _persistentValue.CrossDosePumpFactor = targetPumpFactor;
            ReservoirsPersistentManager.Instance.UpdatePersistentValue(_moduleName);
        }
        /// 
        /// Reset Start
        /// 
        public bool ResetCrossDose()
        {                           
            return _crossDoseResetRoutine.Start() == RState.Running;
        }
        /// 
        /// Reset Start Monitor
        /// 
        /// 
        public bool ResetCrossDoseMonitor()
        {
            RState result = _crossDoseResetRoutine.Monitor();
            if (result == RState.Failed || result == RState.Timeout)
            {
                LOG.WriteLog(eEvent.WARN_RESERVOIR, _moduleName, "Reset Cross Dose failed");
                return false;
            }
            return result == RState.End;
        }
        #endregion
    }
}