using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using CyberX8_Core;
using CyberX8_RT.Devices.Reservoir;
using MECF.Framework.Common.Routine;
using MECF.Framework.Common.ToolLayout;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CyberX8_RT.Devices.Metal
{
    public class CompactMembranFillRoutine : RoutineBase, IRoutine
    {
        private enum ANFillStep
        {
            ANPump,
            ANFill,
            Delay,
            CheckANLimitFlow,
            End,
        }

        #region 常量 
        private const string A = "A";
        private const string FILLING = "Filling";
        private const double AN_FLOW_LIMIT = 0.2;
        #endregion

        #region 内部变量
        /// <summary>
        /// 面
        /// </summary>
        private string _side = "";
        /// <summary>
        /// Reservoir设备对象
        /// </summary>
        private CompactMembranReservoirDevice _reservoirDevice;
        /// <summary>
        /// Metal设备对象
        /// </summary>
        private CompactMembranMetalDevice _metalDevice;
        /// <summary>
        /// 延迟5S
        /// </summary>
        private int _delay = 5000;
        /// <summary>
        /// AN Pump
        /// </summary>
        private bool _anIsPumpOn = false;
        #endregion

        /// <summary>
        /// 构造函数
        /// </summary>
        /// <param name="module"></param>
        public CompactMembranFillRoutine(string module,string side) : base(module)
        {
            _side = side;
        }

        /// <summary>
        /// 中止
        /// </summary>
        public void Abort()
        {
            Runner.Stop("Manual Abort");
        }
        /// <summary>
        /// 监控
        /// </summary>
        /// <returns></returns>
        public RState Monitor()
        {
            Runner.RunIf(ANFillStep.ANPump,!_anIsPumpOn, ANPumpOn,_delay_1ms)
                .Run(ANFillStep.ANFill, ANFillOn, _delay_1ms)
                .Delay(ANFillStep.Delay, _delay)
                .Run(ANFillStep.CheckANLimitFlow, CheckAnLimitFlow, _delay_1ms)
                .End(ANFillStep.End, UpdateAnFlowStatus, _delay_1ms);
            return Runner.Status;
        }
        /// <summary>
        /// AN Pump On
        /// </summary>
        /// <returns></returns>
        private bool ANPumpOn()
        {
            return _reservoirDevice.AnPumpOnOperation("", null);
        }
        /// <summary>
        /// AN Fill On
        /// </summary>
        /// <returns></returns>
        private bool ANFillOn()
        {
            bool result = false;
            if(_side==A)
            {
                result= _metalDevice.AnSideAFillOn("", null);
            }
            else
            {
                result = _metalDevice.AnSideBFillOn("", null);
            }

            return result;
        }
        /// <summary>
        /// 校验流量是否超过最小值
        /// </summary>
        /// <returns></returns>
        private bool CheckAnLimitFlow()
        {
            double anFlow = 0;
            if (_side == A)
            {
                anFlow = _metalDevice.ANACellFlow.CounterValue;
            }
            else
            {
                anFlow=_metalDevice.ANBCellFlow.CounterValue;
            }
            if(anFlow<=AN_FLOW_LIMIT)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, $"AN Flow {anFlow} is not over {AN_FLOW_LIMIT}");
                return false;
            }
            return true;
        }
        /// <summary>
        /// 更新AN Flow状态
        /// </summary>
        /// <returns></returns>
        private bool UpdateAnFlowStatus()
        {
            if (_side == A) 
            {
                _metalDevice.ANACellFlow.Status = "Filling";
            }
            return true;
        }

        /// <summary>
        /// 启动
        /// </summary>
        /// <param name="objs"></param>
        /// <returns></returns>
        public RState Start(params object[] objs)
        {
            _reservoirDevice = GetReservoirDevice();
            _anIsPumpOn = _reservoirDevice.ReservoirData.ANPump != 0;
            _metalDevice = DEVICE.GetDevice<CompactMembranMetalDevice>(Module);
            if (!CheckPreCondition())
            {
                return RState.Failed;
            }
            return Runner.Start(Module, "Start AN Fill");
        }


        /// <summary>
        /// 获取Reservoir设备
        /// </summary>
        /// <returns></returns>
        private CompactMembranReservoirDevice GetReservoirDevice()
        {
            string reservoir = ReservoirItemManager.Instance.GetReservoirByMetal(Module);
            return DEVICE.GetDevice<CompactMembranReservoirDevice>(reservoir);
        }
        /// <summary>
        /// 校验前置条件
        /// </summary>
        /// <returns></returns>
        private bool CheckPreCondition()
        {
            if(_reservoirDevice==null)
            {
                LOG.WriteLog(eEvent.ERR_METAL, Module, "Reservoir is null");
                return false;
            }
            return true;
        }
    }
}