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 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
        }

        bool hasWafer;

        //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 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)
        {
            //servo = DEVICE.GetDevice<NAISServo>($"{Module}.NAISServo");

            //_timeout = SC.GetValue<int>($"NAISServo.UpTimeout");
            _rotationSpeed = SC.GetValue<int>($"PM.{Module}.ProcessIdle.RotationSpeed");

            _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
            {
                EnableRotation((int)RoutineStep.EnableRotation, 5);
                SetRotationValveAndNoWait((int)RoutineStep.SetRotation1, _rotationSpeed);

                TimeDelay((int)RoutineStep.TimeDelay1, _servoUpDelay);

                SetConfinementRingUpAndWait((int)RoutineStep.SetServoUp, 30);

                ExecuteRoutine((int)RoutineStep.SetChamberPressure, _pmServoToPressure);

                TimeDelay((int)RoutineStep.TimeDelay8, 1);

                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);
                }

                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");
        }
    }
}
