using Aitex.Core.RT.Device;
using Aitex.Core.RT.Device.Devices;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Routine;
using Aitex.Core.RT.SCCore;
using MECF.Framework.Common.Equipment;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MFCs;
using SicModules.PMs.Routines.Base;
using System.Collections.Generic;
using System.Diagnostics;

namespace SicModules.PMs.Routines
{
    public class PMVentRoutine : PMBaseRoutine
    {
        private enum RoutineStep
        {
            RotationEnable,
            HeatEnable,
            VentPumpClose,
            ArSupply,

            SetGroupA,
            SetGroupB,
            SetGroupC,
            SetGroupE,
            SetGroupF,
            SetGroupH,
            SetGroupD,
            SetGroupG,
            SetGroupK,

            SetMFCMode,
            SetPCMode,

            SetM1to16,
            SetM17M18,
            SetM18toM40,
            SetPC,
            SetM291519to38,
            SetGroupJ,
            SetM19to38,

            SetGasOut,
            SetTv,

            SetGasIn1,      //V68
            OpenFinal1,     //V91-96
            SetMfcFinal1,   //M32-38
            SetMfc19to26,

            SetTVCloseMode,
            SetTvPositionToZero,
            CheckPM1000,

            SetGasIn2,
            SetGroupJOpen,
            SetM291519to26,

            OpenFinal2,
            SetMfcFinal2,
            WaitPmPressureUp,
            WaitPmPressureUp1,

            SetEPV1,
            SetEPV2,
            SetTvMode,
            SetEPVV1,
            SetMfc28to40Special,
            SetMfc28to40Default,


            SetPC567Close,
            SetPC567Mode,
            SetPC567Default,
            CheckFinal1Open,

            SetV76,
            SetV75,
            SetV31,
            SetV32,
            SetV35V36,
            SetV103,
            SetV105,
            SetGroupV25,

            SetV92V93V95,
            SetV94,
            SetV96,
            SetV68,
            SetM32M35M37,
            SetM36,
            SetM38,

            TimeDelay1,
            TimeDelay2,
            TimeDelay3,
            TimeDelay4,
            TimeDelay5,
            TimeDelay6,
            TimeDelay7,
            TimeDelay8,
            TimeDelay9,
            TimeDelay10,
            TimeDelay11,
            TimeDelay18,
            TimeDelay20,
            TimeDelay21,
            TimeDelay22,
            Notify1,
        }

        private IoThrottleValve2 _IoThrottle;
        private IoInterLock _pmIoInterLock;


        private int _rotationCheckSpeed = 0; //设置旋转速度为0后检查是否转速低于此数值
        private int _rotationCloseTimeout;   //旋转停止超时
        private int _IoValueOpenCloseTimeout = 10; //开关超时时间
        private int _heatTimeOut = 5;             //Heat关闭等待Di反馈超时时间

        private int _waitPMPressureUpTimeout = 300;     //等待反应腔压力到达1000的超时时间

        private int _routineTimeOut;
        private double _ventBasePressure;

        private Stopwatch _swTimer = new Stopwatch();
        public PMVentRoutine(ModuleName module, PMModule pm) : base(module, pm)
        {
            Module = module.ToString();
            Name = "Vent";

            _IoThrottle = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV");
            _pmIoInterLock = DEVICE.GetDevice<IoInterLock>($"{Module}.PMInterLock");
        }

        public override Result Start(params object[] objs)
        {
            Reset();

            _rotationCloseTimeout = SC.GetValue<int>($"PM.{Module}.RotationCloseTimeout");

            _routineTimeOut = SC.GetValue<int>($"PM.{Module}.Vent.RoutineTimeOut");
            _ventBasePressure = SC.GetValue<double>($"PM.{Module}.Vent.VentBasePressure");

            _waitPMPressureUpTimeout = SC.GetValue<int>($"PM.{Module}.Vent.VentTimeout");

            currentPressureUpOrDown = PressureUpOrDown.None;
            _swTimer.Restart();
            _finalOpen = false;

            if (!_pmIoInterLock.SetPMVentRoutineRunning(true, out string reason))
            {
                EV.PostAlarmLog(Module, $"can not Vent,{reason}");
                return Result.FAIL;
            }

            Notify("Start");
            return Result.RUN;
        }

        public override Result Monitor()
        {
            try
            {
                CheckRoutineTimeOut();

                //DOR Pump 抽真空。关闭V76,打开V75
                SetIoValueByGroup((int)RoutineStep.SetV76, IoGroupName.V76, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetV75, IoGroupName.V75, true, _IoValueOpenCloseTimeout);

                //旋转停止,加热停止
                SetHeatEnable((int)RoutineStep.HeatEnable, false, _heatTimeOut);
                SetRotationValve((int)RoutineStep.RotationEnable, _rotationCheckSpeed, false, _rotationCloseTimeout);

                //关闭V72,打开V25
                SetIoValueByGroup((int)RoutineStep.VentPumpClose, IoGroupName.VentPump, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupV25, IoGroupName.V25, true, _IoValueOpenCloseTimeout);

                //打开V31,打开V32
                SetIoValueByGroup((int)RoutineStep.SetV31, IoGroupName.V31, true, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetV32, IoGroupName.V32, true, _IoValueOpenCloseTimeout);

                //5、 打开 V35(H2N2.Line1)、 V36（H2N2.Line2） , 关闭 B/ C / E / F / H / K Valves,打开 D/ G Valves 。
                SetIoValueByGroup((int)RoutineStep.SetV35V36, IoGroupName.V35V36, true, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupB, IoGroupName.B, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupC, IoGroupName.C, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupE, IoGroupName.E, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupF, IoGroupName.F, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupH, IoGroupName.H, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupK, IoGroupName.K, false, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupD, IoGroupName.D, true, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetGroupG, IoGroupName.G, true, _IoValueOpenCloseTimeout);

                //6、 M1-M17 设定为 default 值， 所有 PC 设定为 default 值（PC1-PC9） ，M18 - M40（除 M30\M34\M39） MFC 5s ramp 到 0。
                SetMfcModeToNormalByGroup((int)RoutineStep.SetMFCMode, MfcGroupName.All);
                SetPcToDefault((int)RoutineStep.SetPC, _lstPcList);
                SetMfcToDefaultByGroup((int)RoutineStep.SetM18toM40, MfcGroupName.M18toM40No303439, 5);

                //7、 关闭蝶阀， 再关闭 EPV2
                SetThrottleToCloseMode((int)RoutineStep.SetTVCloseMode, _IoThrottle, 8);
                SetThrottleDisable((int)RoutineStep.SetTvPositionToZero, _IoThrottle, 8);
                TimeDelay((int)RoutineStep.TimeDelay1, 1);
                SetIoValueByGroup((int)RoutineStep.SetEPV2, IoGroupName.EPV2, false, _IoValueOpenCloseTimeout);

                //8、 打开 A Valves（V33S(SH.H2/N2 Switch); V67、 V68(N2.Supply） ).
                SetIoValueByGroup((int)RoutineStep.SetGroupA, IoGroupName.A, true, _IoValueOpenCloseTimeout);

                //9 、 打 开 V87 （ SHPurge.Final ）、 V88 （ OuterGas.Final ）、 V89 （ InnerGas.Final ）、 V90（MiddleGas.Final） 、 V91（OpticPurge.Final）、 V97（CarryGas.Final） ；
                //M27、 M28、 M29、 M31、 M33、 M40 依次设定 3S ramp 到 default 值 ；
                SetIoValueByGroup((int)RoutineStep.OpenFinal2, IoGroupName.Final2, true, _IoValueOpenCloseTimeout);
                SetMfcToDefaultByGroup((int)RoutineStep.SetMfcFinal2, MfcGroupName.Final2, 3);

                //10、 打开 V92（GasRingPurge.Final）、 V93（ChamberPurge.Final）、 V95（ConfinementRing.Final）；等待 3S
                SetIoValueByGroup((int)RoutineStep.SetV92V93V95, IoGroupName.V92V93V95, true, _IoValueOpenCloseTimeout);
                TimeDelay((int)RoutineStep.TimeDelay2, 3);

                //11、 M32、 M35、 M37 依次设定 3S ramp 到 default 值 ； 等待 3S，
                SetMfcToDefaultByGroup((int)RoutineStep.SetM32M35M37, MfcGroupName.M32M35M37, 3);

                //12、 打开 J Valves ；设置 M18-M26 3s ramp 到 default 值。
                //等到腔体压力达到 900 mbar打开 V94（RotationUpPurge.Final）、 M36 设定 5S ramp 到 default 值；
                //等待 3S，打开 V96（HeaterWF.Final）； M38 设定 5S ramp 到 default 值；
                SetIoValueByGroup((int)RoutineStep.SetGroupJOpen, IoGroupName.J, true, _IoValueOpenCloseTimeout);
                WaitPMPressureAndSetMfcSpecial((int)RoutineStep.WaitPmPressureUp1, 900, _waitPMPressureUpTimeout);
                SetIoValueByGroup((int)RoutineStep.SetV94, IoGroupName.V94, true, _IoValueOpenCloseTimeout);
                SetMfcToDefaultByGroup((int)RoutineStep.SetM36, MfcGroupName.M36, 5);
                TimeDelay((int)RoutineStep.TimeDelay3, 3);
                SetIoValueByGroup((int)RoutineStep.SetV96, IoGroupName.V96, true, _IoValueOpenCloseTimeout);
                SetMfcToDefaultByGroup((int)RoutineStep.SetM38, MfcGroupName.M38, 5);

                //13、 压力达到 1020，结束
                NotifyInfo((int)RoutineStep.Notify1, $"Wait pm pressure to {_ventBasePressure} mbar!");
                WaitPMPressureAndSetMfcSpecial((int)RoutineStep.WaitPmPressureUp, _ventBasePressure, _waitPMPressureUpTimeout); //等待反应腔压力大于1000 

            }
            catch (RoutineBreakException)
            {
                return Result.RUN;
            }
            catch (RoutineFaildException)
            {
                return Result.FAIL;
            }

            _pmIoInterLock.SetPMVentRoutineRunning(false, out _);
            Notify($"Finished ! Elapsed time: {(int)(_swTimer.ElapsedMilliseconds / 1000)} s");
            _swTimer.Stop();

            return Result.DONE;
        }

        public override void Abort()
        {
            _pmIoInterLock.SetPMVentRoutineRunning(false, out _);
            PmDevice._ioThrottleValve.StopRamp();
            PmDevice.SetMfcStopRamp(PmDevice.GetMfcListByGroupName(MfcGroupName.All));
            PmDevice.SetRotationServo(0, 0);

            base.Abort();
        }

        private void CheckRoutineTimeOut()
        {
            if (_routineTimeOut > 10)
            {
                if ((int)(_swTimer.ElapsedMilliseconds / 1000) > _routineTimeOut)
                {
                    EV.PostAlarmLog(Module, $"Routine TimeOut! over {_routineTimeOut} s");
                    throw (new RoutineFaildException());
                }
            }
        }

    }
}