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.Common.SubstrateTrackings;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.MFCs;
using SicModules.PMs.Routines.Base;

namespace SicModules.PMs.Routines
{
    class PMPostTransferRoutine : PMBaseRoutine
    {
        enum RoutineStep
        {
            SetUpLimit,
            SetBlockOn,
            Delay,
            WaitStatusCorrect,
            SetBlockOff,
            EnableRotation,
            EnableHeater,
            SetRotation1,
            WaitRotation1,
            SetTC1Mode, 
            SetTC1Ratio, 
            SetTC1Ref,
            SetTC2Mode, 
            SetTC2Ratio, 
            SetTC2Ref,
            SetChamberPressure,
            EnableTC1,
            EnableTC2,
            SetServoUp,
            SetScrReset,

            TimeDelay1,
            TimeDelay2,
            TimeDelay3,
            TimeDelay4,
            TimeDelay5,
            TimeDelay6,
            TimeDelay7,
            TimeDelay8,
            TimeDelay9,
            TimeDelay10,
            TimeDelay11,
            TimeDelay12,
            TimeDelay13,
            TimeDelay14,
            TimeDelay15,

            SetV31, 
            SetV32, 
            SetV35V36, 
            SetGroupB, 
            SetGroupC, 
            SetGroupE, 
            SetGroupF, 
            SetGroupH, 
            SetGroupK, 
            SetGroupD, 
            SetGroupG, 
            SetM1toM17, 
            SetPC, 
            SetM18toM40, 
            SetEPV2, 
            SetGroupJ, 
            SetV72, 
            SetV25, 
            SetPressureDown, 
            SetTVto300
        }

        bool hasWafer;

        private IoThrottleValve2 _IoThrottle;
        private double _throttleFinalPressure = 300;//蝶阀最终调整对的压力
        private double _pmPressureMaxDiff;          //蝶阀与目标压力的差值范围(认为调整到位了)
        private int _throttleTimeout;               //蝶阀调整到指定压力的超时时间

        //private int _timeout;
        private int _rotationSpeed = 60;

        private bool _psuHeatEnable = false;          //是否启用PSU 加热
        private int _psuHeatMode = 0;
        //private float _psuPowerRef = 0;
        private float _psuL1Ratio = 0;
        private float _psuL2Ratio = 0;
        private float _psuL3Ratio = 0;

        private bool _scrHeatEnable = false;          //是否启用SCR 加热
        private int _scrHeatMode = 0;
        //private float _scrPowerRef = 0;
        private float _scrL1Ratio = 0;
        private float _scrL2Ratio = 0;
        private float _scrL3Ratio = 0;

        private int _IoValueOpenCloseTimeout = 10; //开关超时时间

        private double _targetPressure;
        private PMServoToPressure _pmServoToPressure;
        private bool _needEnableHeat = true;

        private int _servoUpDelay;

        //private NAISServo servo;

        public PMPostTransferRoutine(ModuleName module, PMModule pm1) : base(module, pm1)
        {
            Module = module.ToString();
            Name = "Post Transfer Routine";

            _pmServoToPressure = new PMServoToPressure(module, pm1);
        }


        public void Init(bool needEnableHeat)
        {
            _needEnableHeat = needEnableHeat;
        }

        public void Init(float basePressure, int ventDelayTime)
        {

        }


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

            _IoThrottle = DEVICE.GetDevice<IoThrottleValve2>($"{Module}.TV");
            _rotationSpeed = SC.GetValue<int>($"PM.{Module}.ProcessIdle.RotationSpeed");

            _pmPressureMaxDiff = SC.GetValue<double>($"PM.{Module}.ThrottlePressureMaxDiff");
            _throttleFinalPressure = SC.GetValue<double>($"PM.{Module}.ProcessIdle.FinalPressure");
            _throttleTimeout = SC.GetValue<int>($"PM.{Module}.ThrottlePressureTimeout");

            _psuHeatEnable = SC.GetValue<bool>($"PM.{Module}.ProcessIdle.PSUHeaterEnable");
            _psuHeatMode = SC.GetValue<int>($"PM.{Module}.ProcessIdle.PSUHeaterMode");
            //_psuPowerRef = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUPowerRef");
            _psuL1Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUInnerRatio");
            _psuL2Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUMiddleRatio");
            _psuL3Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.PSUOuterRatio");

            _scrHeatEnable = SC.GetValue<bool>($"PM.{Module}.ProcessIdle.SCRHeaterEnable");
            _scrHeatMode = SC.GetValue<int>($"PM.{Module}.ProcessIdle.SCRHeaterMode");
            //_scrPowerRef = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRPowerRef");
            _scrL1Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRUpperRatio");
            _scrL2Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRMiddleRatio");
            _scrL3Ratio = (float)SC.GetValue<double>($"PM.{Module}.ProcessIdle.SCRLowerRatio");
            _targetPressure = SC.GetValue<double>($"PM.{Module}.ProcessIdle.FinalPressure");

            _servoUpDelay = SC.GetValue<int>($"PM.{Module}.PreProcess.ServoBeforeUpDelay");

            _pmServoToPressure.Init(_targetPressure);


            hasWafer = WaferManager.Instance.CheckHasWafer(Module, 0);

            Reset();

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


        public override Result Monitor()
        {
            try 
            {
                //1、 打开 V31(H2.Supply)、 V32(Ar.Supply)。
                SetIoValueByGroup((int)RoutineStep.SetV31, IoGroupName.V31, true, _IoValueOpenCloseTimeout);
                SetIoValueByGroup((int)RoutineStep.SetV32, IoGroupName.V32, true, _IoValueOpenCloseTimeout);
                //2、 打开 V35(H2N2.Line1)、 V36(H2N2.Line2)，关闭 B/ C / E / F / H / KValves,打开 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);
                //3、 M1 - M17 设定为 default 值，所有 PC 设定为 default 值(PC1 - PC9)。
                SetMfcToDefaultByGroup((int)RoutineStep.SetM1toM17, MfcGroupName.M1toM17, 0);
                SetPcToDefault((int)RoutineStep.SetPC, _lstPcList);
                //4、 M18 - M40（除 M30\M34\M39)） MFC 3s ramp 到 default 值。
                SetMfcToDefaultByGroup((int)RoutineStep.SetM18toM40, MfcGroupName.M18toM40No303439, 3);
                //5、 打开 EPV2。
                SetIoValueByGroup((int)RoutineStep.SetEPV2, IoGroupName.EPV2, true, _IoValueOpenCloseTimeout);
                //6、打开 J Valves
                SetIoValueByGroup((int)RoutineStep.SetGroupJ, IoGroupName.J, true, _IoValueOpenCloseTimeout);
                //7、打开 V72(GasBox.Vent.Pump） 关闭 V25(GasBox.Vent.Bypass)， 反应腔压力伺服到300mbar（可配置）
                SetIoValueByGroup((int)RoutineStep.SetV72, IoGroupName.VentPump, true, _IoValueOpenCloseTimeout);
                TimeDelay((int)RoutineStep.TimeDelay5, 1);
                SetIoValueByGroup((int)RoutineStep.SetV25, IoGroupName.V25, false, _IoValueOpenCloseTimeout);
                SetThrottleToTargetAndNoWait((int)RoutineStep.SetPressureDown, _IoThrottle, _throttleFinalPressure);
                WaitThrottleToPressureAndSetMfcSpecial((int)RoutineStep.SetTVto300, _IoThrottle, _throttleFinalPressure, _pmPressureMaxDiff, _throttleTimeout);
                //8、设定转速（可配置）
                EnableRotation((int)RoutineStep.EnableRotation, 5);
                SetRotationValveAndNoWait((int)RoutineStep.SetRotation1, _rotationSpeed);

                //9、加热使能（PSU 和 SCR）（可配置）
                if (_psuHeatEnable && _needEnableHeat)
                {
                    SetPSUEnable((int)RoutineStep.EnableTC1, true, 5);

                    SetPSUHeatMode((int)RoutineStep.SetTC1Mode, _psuHeatMode);
                    TimeDelay((int)RoutineStep.TimeDelay9, 1);
                    SetPSUHeatRatio((int)RoutineStep.SetTC1Ratio, _psuL1Ratio, _psuL2Ratio, _psuL3Ratio);
                }
                if (_scrHeatEnable && _needEnableHeat)
                {
                    SetSCRReset((int)RoutineStep.SetScrReset);
                    TimeDelay((int)RoutineStep.TimeDelay10, 1);

                    SetSCREnable((int)RoutineStep.EnableTC2, true, 5);

                    SetSCRHeatMode((int)RoutineStep.SetTC2Mode, _scrHeatMode);
                    TimeDelay((int)RoutineStep.TimeDelay11, 1);
                    SetSCRHeatRatio((int)RoutineStep.SetTC2Ratio, _scrL1Ratio, _scrL2Ratio, _scrL3Ratio);
                }

                TimeDelay((int)RoutineStep.TimeDelay8, 1);
                WaitRotationValve((int)RoutineStep.WaitRotation1, _rotationSpeed, true, _rotationSpeed / 2);
            }
            catch (RoutineBreakException)
            {
                return Result.RUN;
            }
            catch (RoutineFaildException)
            {
                return Result.FAIL;
            }

            Notify("Finished");

            return Result.DONE;
        }

        //private void ServoUpLimit(int id, PMModuleBase pm, int timeout)
        //{
        //    Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
        //    {
        //        Notify($"Run {pm.Name} set Block No High.");

        //        //if (!servo.SetBlockNoHigh())
        //        //{
        //        //    Stop(reason);
        //        //    return false;
        //        //}
        //        servo.SetBlockNoHigh();
        //        return true;
        //    }, () =>
        //    {
        //        if (servo.AlarmStatus)
        //        {
        //            Stop($"{pm.Name} Servo in error State.");
        //            return null;
        //        }
        //        if (!servo.IsBusy)
        //            return true;

        //        return false;

        //    }, timeout * 1000);

        //    if (ret.Item1)
        //    {
        //        if (ret.Item2 == Result.FAIL)
        //        {
        //            throw (new RoutineFaildException());
        //        }
        //        else if (ret.Item2 == Result.TIMEOUT) //timeout
        //        {
        //            Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
        //            throw (new RoutineFaildException());
        //        }
        //        else
        //            throw (new RoutineBreakException());
        //    }
        //}
        //private void ServoBlockOn(int id, PMModuleBase pm, int timeout)
        //{
        //    Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
        //    {
        //        Notify($"Run {pm.Name} set Stb On.");

        //        //if (!servo.SetBlockNoHigh())
        //        //{
        //        //    Stop(reason);
        //        //    return false;
        //        //}
        //        servo.SetStbOn();
        //        return true;
        //    }, () =>
        //    {
        //        if (servo.AlarmStatus)
        //        {
        //            Stop($"{pm.Name} Servo in error State.");
        //            return null;
        //        }
        //        if (!servo.IsBusy)
        //        {
        //            PMDevice.ServoStatus = ServoStatus.Uping;
        //            return true;
        //        }

        //        return false;

        //    }, timeout * 1000);

        //    if (ret.Item1)
        //    {
        //        if (ret.Item2 == Result.FAIL)
        //        {
        //            throw (new RoutineFaildException());
        //        }
        //        else if (ret.Item2 == Result.TIMEOUT) //timeout
        //        {
        //            Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
        //            throw (new RoutineFaildException());
        //        }
        //        else
        //            throw (new RoutineBreakException());
        //    }
        //}
        //private void ServoBlockOff(int id, PMModuleBase pm, int timeout)
        //{
        //    Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
        //    {
        //        Notify($"Run {pm.Name} set Stb Off.");

        //        //if (!servo.SetBlockNoHigh())
        //        //{
        //        //    Stop(reason);
        //        //    return false;
        //        //}
        //        servo.SetStbOff();
        //        return true;
        //    }, () =>
        //    {
        //        if (servo.AlarmStatus)
        //        {
        //            Stop($"{pm.Name} Servo in error State.");
        //            return null;
        //        }
        //        if (!servo.IsBusy)
        //            return true;

        //        return false;

        //    }, timeout * 1000);

        //    if (ret.Item1)
        //    {
        //        if (ret.Item2 == Result.FAIL)
        //        {
        //            throw (new RoutineFaildException());
        //        }
        //        else if (ret.Item2 == Result.TIMEOUT) //timeout
        //        {
        //            Stop($"{pm.Name} prepare vent timeout, over {timeout} seconds");
        //            throw (new RoutineFaildException());
        //        }
        //        else
        //            throw (new RoutineBreakException());
        //    }
        //}
        //private void WaitStatusCorrect(int id, PMModule pm, int timeout)
        //{
        //    Tuple<bool, Result> ret = ExecuteAndWait(id, () =>
        //    {
        //        Notify($"Run {pm.Name} Wait, Wait Status Correct");

        //        return true;
        //    }, () =>
        //    {
        //        if (servo.AlarmStatus)
        //        {
        //            Stop($"{pm.Name} Servo in error State error");
        //            return null;
        //        }
        //        if ((!servo.MotorBusy && servo.PositionComplete) && pm.ConfinementRing.IsUp)
        //        {
        //            PMDevice.ServoStatus = ServoStatus.Up;
        //            return true;
        //        }
        //        return false;

        //    }, timeout * 1000);

        //    if (ret.Item1)
        //    {
        //        if (ret.Item2 == Result.FAIL)
        //        {
        //            throw (new RoutineFaildException());
        //        }
        //        else if (ret.Item2 == Result.TIMEOUT) //timeout
        //        {
        //            Stop($"{pm.Name} vent timeout, over {timeout} seconds");
        //            throw (new RoutineFaildException());
        //        }
        //        else
        //            throw (new RoutineBreakException());
        //    }
        //}

        public override void Abort()
        {
            if (!PmDevice.StopVent(out string reason))
            {
                EV.PostWarningLog(Module, reason);
            }

            Stop("aborted");
        }
    }
}
