using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using PunkHPX8_Core;
using PunkHPX8_RT.Modules.Reservoir;
using PunkHPX8_RT.Modules.SRD;
using MECF.Framework.Common.Beckhoff.ModuleIO;
using MECF.Framework.Common.Persistent.Reservoirs;
using MECF.Framework.Common.Persistent.Temperature;
using MECF.Framework.Common.ProcessCell;
using MECF.Framework.Common.RecipeCenter;
using MECF.Framework.Common.ToolLayout;
using MECF.Framework.Common.TwinCat;
using System;
using System.Net;
using System.Reflection;
namespace PunkHPX8_RT.Devices.Reservoir
{
    public class DosingSystemHelper
    {
        #region 常量
        public enum BottleLevelState
        {
            Empty,
            Full,
            Warning,
        }
        
        public enum DosingOperation
        {
            None,
            ManualDosing,
            AutoDosing,
        }
        #endregion
        #region 内部变量
        /// 
        /// ModuleName
        /// 
        private string _moduleName;
        /// 
        /// ReplenName
        /// 
        private string _replenName;
        /// 
        /// ReplenID
        /// 
        private int _replenId;
        /// 
        /// ReservoirDosingRoutine
        /// 
        private ReservoirDosingRoutine _reservoirDosingRoutine;        
        /// 
        /// 当前加载Recipoe
        /// 
        private RdsRecipe _currentRecipe;
        /// 
        /// 当次自动补液体积
        /// 
        private double _autoDosingVolume;
        /// 
        /// 最小补液体积
        /// 
        private double _minDoseAmount;
        /// 
        /// Replen Persistent
        /// 
        private ReplenPersistentValue _persistentValue;
        /// 
        /// Reservoir Usage
        /// 
        private ReservoirUsage _reservoirUsage;
        #endregion
        #region 属性
        /// 
        /// 当次自动补液体积
        /// 
        public double AutoDosingVolume { get { return _autoDosingVolume; } }
        /// 
        /// Dosing状态
        /// 
        public RState DosingState { get { return _reservoirDosingRoutine.Monitor(); } }
        
        #endregion
        /// 
        /// 构造函数
        /// 
        /// 
        public DosingSystemHelper(string moduleName, string replenName)
        {
            _moduleName = moduleName;
            _replenName = replenName;
            _replenId = int.Parse(replenName.Substring(6, 1));
            _persistentValue = ReplenPersistentManager.Instance.GetReplenPersistentValue(_moduleName, _replenName);
            _reservoirDosingRoutine = new ReservoirDosingRoutine(_moduleName,_replenName);
            
        }
        #region Operation
        /// 
        /// 开始Dosing
        /// 
        public bool StartDosing(double targetVolume, bool isAutoMode) 
        {
            _persistentValue.IsDosingRunning = true;
            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
            return _reservoirDosingRoutine.Start(targetVolume, isAutoMode) == RState.Running;          
        }
        /// 
        /// 停止Dosing
        /// 
        public bool StopDosing()
        {
            _persistentValue.IsDosingRunning = false;
            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);            
            _reservoirDosingRoutine.Abort();
            return true;
        }  
        /// 
        /// Dosing超时监控
        /// 
        /// 
        public bool DosingTimeOutMonitor()
        {
            RState result = _reservoirDosingRoutine.Monitor();
            if(result == RState.Failed || result == RState.Timeout)
            {
                return false;
            }
            return true;
        }
        /// 
        /// 监控AutoDose触发时机
        /// 
        /// 
        public bool AutoDosingMonitor()
        {
            bool result = false;
            double targetVolume = 0;
            double currentDosingAmpHour = 0;
            _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
            //最小补液体积
            if (SC.ContainsItem($"Reservoir.{_moduleName}.InitialDosingSpeed"))
            {
                _minDoseAmount = SC.GetValue($"Reservoir.{_moduleName}.MinDoseAmount");
            }
            //当前电量
            if(_reservoirUsage != null) currentDosingAmpHour = _reservoirUsage.TotalUsage;
            //累计电量(Ah)
            double deltAmpHour = currentDosingAmpHour - _persistentValue.AutoDosingStartAmpHour;
            //累计时间(hr)
            double deltHour = DateTime.Now.Subtract(_persistentValue.AutoDosingStartTime).TotalHours;
            if (_currentRecipe != null)
            {
                if (_currentRecipe.ReplenEnable)
                {
                    if (_currentRecipe.ReplenCurrentBased)
                    {
                        //基于电量计算DoseVolume
                        targetVolume = deltAmpHour * _currentRecipe.ReplenCurrentBasedRate;
                        _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);                       
                        //计算DoseVolume大于MinDoseAmount则开始补液
                        if (targetVolume > _minDoseAmount)
                        { 
                            _autoDosingVolume = targetVolume;
                            result = true;
                        }        
                    }
                    else if(_currentRecipe.ReplenTimeBased)
                    {
                        //基于时间计算DoseVolume
                        targetVolume = deltHour / 24 * _currentRecipe.ReplenTimeBasedRate;
                        _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
                        //计算DoseVolume大于MinDoseAmount则开始补液
                        if (targetVolume > _minDoseAmount)
                        {
                            _autoDosingVolume = targetVolume;
                            result = true;
                        }
                    }
                }else if (_currentRecipe.AutoDoseEnable)
                {
                    _persistentValue.TargetDosingVolume = _minDoseAmount;
                    
                    if (_currentRecipe.AutoCurrentBased)
                    {
                        //累计电量大于AutoDosingStartAmpHour则开始补液
                        targetVolume = _minDoseAmount / _currentRecipe.AutoDoseFrequency * deltAmpHour;
                        _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
                        if (deltAmpHour > _currentRecipe.AutoDoseFrequency)
                        {
                            result = true;
                            _autoDosingVolume = _minDoseAmount;
                        }
                    }
                    else if (_currentRecipe.AutoTimeBased)
                    {
                        //累计时间大于AutoDoseIdleStartTime则开始补液
                        targetVolume = _minDoseAmount / _currentRecipe.AutoDoseIdleStartTime * deltHour;
                        _persistentValue.TargetDosingVolume = Math.Round(targetVolume, 2);
                        if (deltHour > _currentRecipe.AutoDoseIdleStartTime)
                        {
                            result = true;
                            _autoDosingVolume = _minDoseAmount;
                        }
                    }                    
                    
                }
                
            }
            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
            return result;
        }
        /// 
        /// 检查并加载Recipe
        /// 
        /// 
        /// 
        public bool CheckandLoadRecipe(RdsRecipe recipe)
        {
            if (_currentRecipe == recipe)
            {
                return true;
            }
            else if (_currentRecipe == null)
            {
                _currentRecipe = recipe;
                return true;
            }
            else
            {
                _currentRecipe = recipe;
                return false;
            }
        }
        /// 
        /// 记录AutoDosing开始时的时间和电量
        /// 
        public void RecordStartData()
        {
            _reservoirUsage = ReservoirUsageManager.Instance.GetReservoirUsage(_moduleName);
            _persistentValue.AutoDosingStartTime = DateTime.Now;
            if(_reservoirUsage != null) _persistentValue.AutoDosingStartAmpHour = _reservoirUsage.TotalUsage;
            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
        }
        /// 
        /// 设置PumpFactor
        /// 
        public void SetPumpfactor(double targetPumpFactor)
        {
            _persistentValue.ReplenPumpFactor = targetPumpFactor;
            ReplenPersistentManager.Instance.UpdatePersistentValue(_moduleName, _replenName);
        }
        
        #endregion
        
    }
}