using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using Venus_RT.Devices;
using MECF.Framework.Common.Routine;
using System.Diagnostics;
using Venus_Core;
using System;
using Venus_Unity;
using MECF.Framework.Common.DBCore;

namespace Venus_RT.Modules.PMs
{
    class PMLeakCheckRoutine : PMRoutineBase, IRoutine
    {
        private enum LeakCheckStep
        {
            kPumpToBasePressure,
            kPumpingDelay,
            kLeakCheckDelay,
            kEnd,
        }
        public double LeakRate { get; private set; }

        private int _basePressure = 100;
        private int _leakcheckPumpTime = 180;
        private int _leakcheckHoldTime = 300;

        private double _startPressure = 0;
        private double _endPressure = 0;
        private double _leakRate = 30.0;
        private double _leakCheckBasePressure = 1;
        public string CurrentStep;

        Stopwatch _leakCheckTimer = new Stopwatch();
        PMLeakCheckResult pMLeakCheckResult;
        Stopwatch _routineTimer = new Stopwatch();
        public PMLeakCheckRoutine(JetPMBase chamber) : base(chamber)
        {
            Name = "PM Leakcheck";
        }

        public RState Start(params object[] objs)
        {
            if (CheckLid() &&
                CheckSlitDoor() &&
                CheckTurboPump())
            {
                CurrentStep = "Pump To BasePressure";

                Reset();

                _basePressure = SC.GetValue<int>($"{Module}.Pump.PumpBasePressure");
                //_leakcheckPumpTime = SC.GetValue<int>($"{Module}.Pump.LeakCheckPumpingTime");
                //_leakcheckHoldTime = SC.GetValue<int>($"{Module}.Pump.LeakCheckHoldTime");
                //_leakRate = SC.GetValue<double>($"{Module}.Pump.LeakRate");

                _leakcheckPumpTime = (int)(objs[0]);
                _leakcheckHoldTime = (int)(objs[1]);
                _leakRate = (double)(objs[2]);

                _leakCheckBasePressure = SC.GetValue<double>($"{Module}.Pump.LeakCheckBasePressure");

                PreSetValves();
                pMLeakCheckResult = new PMLeakCheckResult();
                pMLeakCheckResult.CheckDate = DateTime.Now.ToString("yyyyMMddHHmm");
                pMLeakCheckResult.CheckMode = "ChamberOnly";
                _routineTimer.Restart();
                return Runner.Start(Module, Name);
            }
            return RState.Failed;
        }

        public RState Monitor()
        {
            Runner.Wait((int)LeakCheckStep.kPumpToBasePressure, PumpingToBasePressure)
                .Run((int)LeakCheckStep.kPumpingDelay, StartPumpDelay, PumpingDelay)
                .Run((int)LeakCheckStep.kLeakCheckDelay, StartLeakCheck, _leakcheckHoldTime * 1000)
                .End((int)LeakCheckStep.kEnd, CalcLeakCheckResult, _delay_50ms);

            return Runner.Status;
        }

        public void Abort()
        {
            CloseAllValves();
        }

        private bool PumpingToBasePressure()
        {
            if (_chamber.ChamberPressure <= _basePressure)
            {
                _leakCheckTimer.Restart();
                return true;
            }
            else
                return false;
        }

        private bool PumpingDelay()
        {
            if (_leakCheckTimer.ElapsedMilliseconds >= _leakcheckPumpTime * 1000)
            {
                if (_chamber.ChamberPressure <= _leakCheckBasePressure)
                    return true;
                else
                {
                    Runner.Stop($"PM Leakcheck失败, 腔体压力 [{_chamber.ChamberPressure}]mTor, 高于LeakCheck Base Pressure: [{_leakCheckBasePressure}] mTor");
                }
            }

            return false;
        }
        private bool StartPumpDelay()
        {
            _chamber.OpenValve(ValveType.GasFinal, false);
            CurrentStep = "Check Pump";
            return true;
        }
        private bool StartLeakCheck()
        {
            CurrentStep = "Leak Check";
            _startPressure = _chamber.ChamberPressure;
            pMLeakCheckResult.StartPressure = _startPressure;

            Notify($"PM 压力开始值 {_startPressure} mt");

            _chamber.TurnPendulumValve(false);
            return true;
        }

        private bool CalcLeakCheckResult()
        {
            _endPressure = _chamber.ChamberPressure;
            pMLeakCheckResult.EndPressure = _endPressure;
            LeakRate = (_endPressure - _startPressure) * 60.0 / _leakcheckHoldTime;
            pMLeakCheckResult.LeakRate = LeakRate;
            if (LeakRate < _leakRate)
            {
                Notify($"PM Leakcheck完成, 压力结束值: {_startPressure} mt, 漏率:{LeakRate} mt/min");
                pMLeakCheckResult.Result = "Success";

            }
            else
            {
                Stop($"PM Leakcheck失败, 腔体漏率 [{LeakRate}] mt/min, 高于 [{_leakRate}] mt/min");
                pMLeakCheckResult.Result = "Fail";
            }
            LeakCheckDataRecorder.Add(_leakcheckHoldTime, (int)_startPressure, (int)_endPressure, LeakRate, pMLeakCheckResult.Result, "ChamberOnly", _chamber.Name);
            _chamber.OpenValve(ValveType.GasFinal, true);
            _chamber.TurnPendulumValve(true);
            pMLeakCheckResult.LeakCheckTime = (int)_routineTimer.ElapsedMilliseconds / 1000;


            //SerializeHelper.Instance.WriteToJsonFile<PMLeakCheckResult>(pMLeakCheckResult, $"LeakCheck/PM/{DateTime.Now.ToString("yyyyMMddHHmm")}.json");
            return true;
        }

        private void PreSetValves()
        {
            _chamber.OpenValve(ValveType.FastPump, false);
            _chamber.OpenValve(ValveType.SoftPump, false);
            _chamber.OpenValve(ValveType.TurboPumpPumping, true);
            _chamber.OpenValve(ValveType.Guage, true);
            _chamber.OpenValve(ValveType.GasFinal, true);




            _chamber.TurnPendulumValve(true);

        }
    }
}