using System;
using System.Collections.Generic;
//using System.
using Venus_RT.Devices;
using Venus_RT.Modules;
using Aitex.Core.RT.Log;
using Venus_Core;
using Aitex.Core.RT.SCCore;
using System.Reflection;
using System.Diagnostics;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
using Aitex.Core.Common.DeviceData;
//#pragma warning disable 0436

namespace Venus_RT.Modules.PMs
{
    class ProcessHelper
    {
        protected JetPMBase Chamber;
        private string Module;
        public RecipeHead m_RecipeHead;

        private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> startHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>();
        private static Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>> checkerHelper = new Dictionary<string, Func<ProcessUnitBase, RecipeStep, RState>>();
        private static Dictionary<string, Action<ProcessUnitBase, RecipeStep>> endHelper = new Dictionary<string, Action<ProcessUnitBase, RecipeStep>>();
        private List<float> rfMatchC1 = new List<float>();
        private List<float> rfMatchC2 = new List<float>();
        private int rfMatchC1C2Index = 0;


        private List<float> biasRfMatchC1 = new List<float>();
        private List<float> biasRfMatchC2 = new List<float>();
        private int biasRfMatchC1C2Index = 0;

        public bool isLoop = false;
        public int loopsteps = 0;
        public int currentStepIndex = 0;

        //private int cycleIndex = 0;
        private bool biasRFSetPointFlag = true;
        public ProcessHelper(JetPMBase pm)
        {
            Chamber = pm;
            Module = pm.Module.ToString();
            Init();
        }

        private void Init()
        {
            startHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_Start(unit, step);
            checkerHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_Check(unit, step);
            endHelper[$"{Module}.PressureByPressureModeUnit"] = (ProcessUnitBase unit, RecipeStep step) => PressureByPressureModeUnit_End(unit, step);

            //startHelper     [$"{Module}.PressureByValveModeUnit"]     = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_Start(unit, step);
            //checkerHelper   [$"{Module}.PressureByValveModeUnit"]     = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_Check(unit, step);
            //endHelper       [$"{Module}.PressureByValveModeUnit"]     = (ProcessUnitBase unit, RecipeStep step) => PressureByValveModeUnit_End(unit, step);

            startHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_Start(unit, step);
            checkerHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_Check(unit, step);
            endHelper[$"{Module}.TCPUnit"] = (ProcessUnitBase unit, RecipeStep step) => TCPUnit_End(unit, step);

            startHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_Start(unit, step);
            checkerHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_Check(unit, step);
            endHelper[$"{Module}.BiasUnit"] = (ProcessUnitBase unit, RecipeStep step) => BiasUnit_End(unit, step);

            startHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_Start(unit, step);
            checkerHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_Check(unit, step);
            endHelper[$"{Module}.GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => GasControlUnit_End(unit, step);

            startHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_Start(unit, step);
            checkerHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_Check(unit, step);
            endHelper[$"{Module}.ESCHVUnit"] = (ProcessUnitBase unit, RecipeStep step) => ESCHVUnit_End(unit, step);

            startHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_Start(unit, step);
            checkerHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_Check(unit, step);
            endHelper[$"{Module}.ProcessKitUnit"] = (ProcessUnitBase unit, RecipeStep step) => ProcessKitUnit_End(unit, step);

            startHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_Start(unit, step);
            checkerHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_Check(unit, step);
            endHelper[$"{Module}.Kepler2200GasControlUnit"] = (ProcessUnitBase unit, RecipeStep step) => Kepler2200GasControlUnit_End(unit, step);

            startHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_Start(unit, step);
            checkerHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_Check(unit, step);
            endHelper[$"{Module}.HeaterUnit"] = (ProcessUnitBase unit, RecipeStep step) => HeaterUnit_End(unit, step);
        }

        private RState PressureByPressureModeUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as PressureByPressureModeUnit;

            if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure)
            {
                if (Chamber.SetPVPressure(ProcessUnit.StartValue))
                {
                    return RState.Running;
                }
            }
            else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve)
            {
                if (Chamber.SetPVPostion(ProcessUnit.StartValue))
                {
                    return RState.Running;
                }
            }
            return RState.Failed;
        }

        private RState PressureByPressureModeUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as PressureByPressureModeUnit;
            if (ProcessUnit.EnableRamp)
            {
                if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure)
                {
                    if (Chamber.SetPVPressure(ProcessUnit.StartValue + (int)((ProcessUnit.TargetValue - ProcessUnit.StartValue) * step.RampFactor())))
                        return RState.Running;
                    else
                        return RState.Failed;
                }
                else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve)
                {
                    if (Chamber.SetPVPressure(ProcessUnit.StartValue + (int)((ProcessUnit.TargetValue - ProcessUnit.StartValue) * step.RampFactor())))
                        return RState.Running;
                    else
                        return RState.Failed;
                }
            }

            if (ProcessUnit.PressureUnitMode == PressureUnitMode.Pressure)
            {
                if (step.Type == StepType.Stable && Chamber.ChamberPressure == ProcessUnit.StartValue)
                {
                    return RState.End;
                }
            }
            else if (ProcessUnit.PressureUnitMode == PressureUnitMode.Valve)
            {
                if (step.Type == StepType.Stable && Chamber.GetPVPosition() == ProcessUnit.StartValue)
                {
                    return RState.End;
                }

            }


            return RState.Running;
        }

        private void PressureByPressureModeUnit_End(ProcessUnitBase unit, RecipeStep step)
        {

        }

        #region Valve Mode已取消,合并到压力模式
        //private RState PressureByValveModeUnit_Start(ProcessUnitBase unit, RecipeStep step)
        //{
        //    var ProcessUnit = unit as PressureByValveModeUnit;
        //    if (Chamber.SetPVPostion(ProcessUnit.StartPosition))
        //    {
        //        return RState.Running;
        //    }
        //    return RState.Failed;
        //}

        //private RState PressureByValveModeUnit_Check(ProcessUnitBase unit, RecipeStep step)
        //{
        //    var ProcessUnit = unit as PressureByValveModeUnit;
        //    if (ProcessUnit.EnableRamp)
        //    {
        //        if (Chamber.SetPVPostion(ProcessUnit.StartPosition + (int)((ProcessUnit.TargetPosition - ProcessUnit.StartPosition) * step.RampFactor())))
        //            return RState.Running;
        //        else
        //            return RState.Failed;
        //    }

        //    return RState.Running;
        //}

        //private void PressureByValveModeUnit_End(ProcessUnitBase unit, RecipeStep step)
        //{

        //}
        #endregion


        private RState TCPUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as TCPUnit;
            if (ProcessUnit.RFPower > 5)
            {
                Chamber.GeneratorSetpower(ProcessUnit.RFPower);
                Chamber.GeneratorPowerOn(true);
            }
            else
            {
                Chamber.GeneratorSetpower(0);
                Chamber.GeneratorPowerOn(false);
            }
            int p1;
            int p2;
            if (ProcessUnit.TuneCapPreset > 0)
            {
                p1 = ProcessUnit.TuneCapPreset;
            }
            else
            {
                p1 = ProcessUnit.AutoTuneCapPreset;
            }
            if (ProcessUnit.LoadCapPreset > 0)
            {
                p2 = ProcessUnit.LoadCapPreset;
            }
            else
            {
                p2 = ProcessUnit.AutoLoadCapPreset;
            }
            Chamber.SetMatchPosition(p1, p2);
            rfMatchC1.Clear();
            rfMatchC1.Clear();
            rfMatchC1C2Index = 0;
            return RState.Running;
        }

        private RState TCPUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            var _scPowerAlarmTime = SC.GetValue<double>($"{Chamber.Name}.Rf.PowerAlarmTime");
            var ProcessUnit = unit as TCPUnit;
            if (ProcessUnit.MaxReflectedPower > 0 && Chamber.ReflectPower > ProcessUnit.MaxReflectedPower && step.ElapsedTime() > _scPowerAlarmTime * 1000)
            {
                LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, RF Reflect Power:{Chamber.ReflectPower} exceeds the Max Limit:{ProcessUnit.MaxReflectedPower}");
                return RState.Failed;
            }

            if (step.ElapsedTime() > m_RecipeHead.RFHoldTime * 1000)
            {
                Chamber.GeneratorSetpower(0);
                Chamber.GeneratorPowerOn(false);
            }

            if (step.ElapsedTime() > rfMatchC1C2Index * 1000)
            {
                rfMatchC1.Add(Chamber.RFMatchC1);
                rfMatchC2.Add(Chamber.RFMatchC2);
                rfMatchC1C2Index += 1;
            }


            return RState.Running;
        }

        private void TCPUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as TCPUnit;
            if (rfMatchC1.Count >= 6)
            {
                float allValue = 0;
                for (int i = 4; i < rfMatchC1.Count; i++)
                {
                    allValue += rfMatchC1[i];
                }
                var average = allValue / (rfMatchC1.Count - 4);
                ProcessUnit.AutoTuneCapPreset = (int)average;
            }
            if (rfMatchC2.Count >= 6)
            {
                float allValue = 0;
                for (int i = 4; i < rfMatchC2.Count; i++)
                {
                    allValue += rfMatchC2[i];
                }
                var average = allValue / (rfMatchC2.Count - 4);
                ProcessUnit.AutoLoadCapPreset = (int)average;
            }

            rfMatchC1.Clear();
            rfMatchC2.Clear();
            rfMatchC1C2Index = 0;
        }

        private RState BiasUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as BiasUnit;
            if (ProcessUnit.BiasRFPower > 5)
            {
                Chamber.GeneratorBiasPowerOn(true);
                if ((ProcessUnit.EnableRamp == false))
                {
                    Chamber.GeneratorBiasSetpower(ProcessUnit.BiasRFPower);
                }
            }
            int p1;
            int p2;
            if (ProcessUnit.BiasTuneCapPreset > 0)
            {
                p1 = ProcessUnit.BiasTuneCapPreset;
            }
            else
            {
                p1 = ProcessUnit.AutoBiasTuneCapPreset;
            }
            if (ProcessUnit.BiasLoadCapPreset > 0)
            {
                p2 = ProcessUnit.BiasLoadCapPreset;
            }
            else
            {
                p2 = ProcessUnit.AutoBiasLoadCapPreset;
            }
            Chamber.SetBiasMatchPosition(p1, p2);
            if (ProcessUnit.BiasGeneratorMode == GeneratorMode.Pulsing)
            {
                Chamber.SetBiasPulseMode(true);
                Chamber.SetBiasPulseRateFreq(ProcessUnit.PulseRateFreq);
                Chamber.SetDiasPulseDutyCycle(ProcessUnit.PulseDutyCycle);
            }
            biasRfMatchC1.Clear();
            biasRfMatchC1.Clear();
            biasRfMatchC1C2Index = 0;
            biasRFSetPointFlag = true;
            return RState.Running;
        }

        private RState BiasUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            var _scPowerAlarmTime = SC.GetValue<double>($"{Chamber.Name}.BiasRf.PowerAlarmTime");

            var ProcessUnit = unit as BiasUnit;
            if (ProcessUnit.BiasMaxReflectedPower > 0 && Chamber.BiasReflectPower > ProcessUnit.BiasMaxReflectedPower && step.ElapsedTime() > _scPowerAlarmTime * 1000)
            {
                LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, Bias Reflect Power:{Chamber.BiasReflectPower} exceeds the Max Limit:{ProcessUnit.BiasMaxReflectedPower}");
                return RState.Failed;
            }

            if (step.ElapsedTime() > m_RecipeHead.BiasRFHoldTime * 1000)
            {
                Chamber.GeneratorBiasSetpower(0);
                Chamber.GeneratorBiasPowerOn(false);
            }
            if (step.ElapsedTime() > biasRfMatchC1C2Index * 1000)
            {
                biasRfMatchC1.Add(Chamber.BiasRFMatchC1);
                biasRfMatchC2.Add(Chamber.BiasRFMatchC2);
                biasRfMatchC1C2Index += 1;
            }
            if (ProcessUnit.EnableRamp)
            {
                //if (step.ElapsedTime() <= 500*cycleIndex)
                //{
                //    return RState.Running;
                //}
                //cycleIndex += 1;
                if (ProcessUnit.TargetMode == TargetMode.Cycle)
                {
                    if ( biasRFSetPointFlag==true)
                    {
                        biasRFSetPointFlag = false;
              
                        Chamber.GeneratorBiasSetpower((float)((ProcessUnit.BiasRFPower + (float)((float)(ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) / ((float)(loopsteps-1) / (float)(currentStepIndex))))));
                    }
                    //float rampFactor = (float)currentStepIndex / (float)(loopsteps-1);
                    //double rampFactor = step.RampFactor();                                 
                    //Chamber.GeneratorBiasSetpower((float)((ProcessUnit.BiasRFPower+  (ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower)/(loopsteps)*currentStepIndex) +  ((double)(ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) / ((double)loopsteps)) * rampFactor));
                }
                else
                {
                    //double rampFactor = step.RampFactor();                 
                    //Chamber.GeneratorBiasSetpower((float)(ProcessUnit.BiasRFPower + (ProcessUnit.TargetBiasRFPower - ProcessUnit.BiasRFPower) * rampFactor));
                }
            }
            return RState.Running;
        }

        private void BiasUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as BiasUnit;
            Chamber.GeneratorBiasSetpower(0);
            Chamber.GeneratorBiasPowerOn(false);
            if (biasRfMatchC1.Count >= 6)
            {
                float allValue = 0;
                for (int i = 4; i < biasRfMatchC1.Count; i++)
                {
                    allValue += biasRfMatchC1[i];
                }
                var average = allValue / (biasRfMatchC1.Count - 4);
                ProcessUnit.AutoBiasTuneCapPreset = (int)average;
            }
            if (biasRfMatchC2.Count >= 6)
            {
                float allValue = 0;
                for (int i = 4; i < biasRfMatchC2.Count; i++)
                {
                    allValue += biasRfMatchC2[i];
                }
                var average = allValue / (biasRfMatchC2.Count - 4);
                ProcessUnit.AutoBiasLoadCapPreset = (int)average;
            }
            biasRfMatchC1.Clear();
            biasRfMatchC1.Clear();
            biasRfMatchC1C2Index = 0;
            //cycleIndex = 0;
            biasRFSetPointFlag = true;
        }

        private RState GasControlUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            Chamber.OpenValve(ValveType.GasFinal, true);
            var ProcessUnit = unit as GasControlUnit;
            Chamber.FlowGas(0, ProcessUnit.Gas1);
            if (ProcessUnit.Gas1 >= 1)
            {
                Chamber.OpenValve(ValveType.PV11, true);
            }
            Chamber.FlowGas(1, ProcessUnit.Gas2);
            if (ProcessUnit.Gas2 >= 1)
            {
                Chamber.OpenValve(ValveType.PV21, true);
            }
            Chamber.FlowGas(2, ProcessUnit.Gas3);
            if (ProcessUnit.Gas3 >= 1)
            {
                Chamber.OpenValve(ValveType.PV31, true);
            }
            Chamber.FlowGas(3, ProcessUnit.Gas4);
            if (ProcessUnit.Gas4 >= 1)
            {
                Chamber.OpenValve(ValveType.PV41, true);
            }
            Chamber.FlowGas(4, ProcessUnit.Gas5);
            Chamber.FlowGas(5, ProcessUnit.Gas6);
            Chamber.FlowGas(6, ProcessUnit.Gas7);
            Chamber.FlowGas(7, ProcessUnit.Gas8);
            return RState.Running;
        }

        private RState GasControlUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as GasControlUnit;
            if (ProcessUnit.EnableRamp)
            {
                double rampFactor = step.RampFactor();
                Chamber.FlowGas(0, ProcessUnit.Gas1 + (ProcessUnit.Gas1Target - ProcessUnit.Gas1) * rampFactor);
                Chamber.FlowGas(1, ProcessUnit.Gas2 + (ProcessUnit.Gas2Target - ProcessUnit.Gas2) * rampFactor);
                Chamber.FlowGas(2, ProcessUnit.Gas3 + (ProcessUnit.Gas3Target - ProcessUnit.Gas3) * rampFactor);
                Chamber.FlowGas(3, ProcessUnit.Gas4 + (ProcessUnit.Gas4Target - ProcessUnit.Gas4) * rampFactor);
                Chamber.FlowGas(4, ProcessUnit.Gas5 + (ProcessUnit.Gas5Target - ProcessUnit.Gas5) * rampFactor);
                Chamber.FlowGas(5, ProcessUnit.Gas6 + (ProcessUnit.Gas6Target - ProcessUnit.Gas6) * rampFactor);
                Chamber.FlowGas(6, ProcessUnit.Gas7 + (ProcessUnit.Gas7Target - ProcessUnit.Gas7) * rampFactor);
                Chamber.FlowGas(7, ProcessUnit.Gas8 + (ProcessUnit.Gas8Target - ProcessUnit.Gas8) * rampFactor);
            }
            return RState.Running;
        }

        private void GasControlUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
            Chamber.FlowGas(0, 0);
            Chamber.FlowGas(1, 0);
            Chamber.FlowGas(2, 0);
            Chamber.FlowGas(3, 0);
            Chamber.FlowGas(4, 0);
            Chamber.FlowGas(5, 0);
            Chamber.FlowGas(6, 0);
            Chamber.FlowGas(7, 0);
        }

        private RState ESCHVUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as ESCHVUnit;

            Chamber.SetESCClampVoltage(ProcessUnit.ESCClampValtage);

            Chamber.SetBacksideHePressure(ProcessUnit.BacksideHelum);
            Chamber.SetBacksideHeThreshold(ProcessUnit.MinHeFlow, ProcessUnit.MaxHeFlow);
            return RState.Running;
        }

        private RState ESCHVUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            if (Chamber.BackSideHeOutOfRange)
            {
                LOG.Write(eEvent.ERR_PROCESS, Chamber.Module, $"Step:{step.StepNo} failed, Backside Helium out of range.");
                return RState.Failed;
            }

            return RState.Running;
        }

        private void ESCHVUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
            Chamber.SetESCClampVoltage(0);
            //Chamber.SetBacksideHePressure(0);
            Chamber.SetBacksideHeThreshold(0, 0);
            //Chamber.OnOffSetESCHV(false);
        }

        private RState ProcessKitUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as ProcessKitUnit;
            return RState.Running;
        }

        private RState ProcessKitUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            var ProcessUnit = unit as ProcessKitUnit;
            return RState.Running;
        }

        private void ProcessKitUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
        }

        private RState Kepler2200GasControlUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            Chamber.OpenValve(ValveType.GasFinal, true);
            var ProcessUnit = unit as Kepler2200GasControlUnit;
            Chamber.FlowGas(0, ProcessUnit.Gas1);
            if (ProcessUnit.Gas1 >= 1)
            {
                Chamber.OpenValve(ValveType.PV11, true);
            }
            Chamber.FlowGas(1, ProcessUnit.Gas2);
            if (ProcessUnit.Gas2 >= 1)
            {
                Chamber.OpenValve(ValveType.PV21, true);
            }
            Chamber.FlowGas(2, ProcessUnit.Gas3);
            if (ProcessUnit.Gas3 >= 1)
            {
                Chamber.OpenValve(ValveType.PV31, true);
            }
            Chamber.FlowGas(3, ProcessUnit.Gas4);
            if (ProcessUnit.Gas4 >= 1)
            {
                Chamber.OpenValve(ValveType.PV41, true);
            }
            Chamber.FlowGas(4, ProcessUnit.Gas5);
            Chamber.FlowGas(5, ProcessUnit.Gas6);

            return RState.Running;
        }

        private RState Kepler2200GasControlUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            return RState.Running;
        }

        private void Kepler2200GasControlUnit_End(ProcessUnitBase unit, RecipeStep step)
        {
            Chamber.FlowGas(0, 0);
            Chamber.FlowGas(1, 0);
            Chamber.FlowGas(2, 0);
            Chamber.FlowGas(3, 0);
            Chamber.FlowGas(4, 0);
            Chamber.FlowGas(5, 0);
        }

        private RState HeaterUnit_Start(ProcessUnitBase unit, RecipeStep step)
        {
            return RState.Running;
        }

        private RState HeaterUnit_Check(ProcessUnitBase unit, RecipeStep step)
        {
            return RState.Running;
        }

        private void HeaterUnit_End(ProcessUnitBase unit, RecipeStep step)
        {

        }
        public bool LoadMethods(ProcessUnitBase unit)
        {
            var className = $"{Module}.{unit.GetType().Name}";
            if (startHelper.ContainsKey(className) && checkerHelper.ContainsKey(className) && endHelper.ContainsKey(className))
            {
                unit.starter = startHelper[className];
                unit.checker = checkerHelper[className];
                unit.end = endHelper[className];

                return true;
            }

            return false;
        }
        //public void loopStep(bool isloop,int loopCount,int loopIndex)
        //{ 
        //    isLoop = isloop;
        //    loopsteps=loopCount;
        //    currentStepIndex = loopIndex;
        //}

        private RState stepStarter(RecipeStep step)
        {
            step.StartStepTimer();
            switch (step.Type)
            {
                case StepType.EndPoint:
                    Chamber.EPDStepStart(step.EPDConfig, step.StepNo);
                    break;
            }
            return RState.Running;
        }

        private RState stepChecker(RecipeStep step)
        {
            switch (step.Type)
            {
                case StepType.Time:
                    return step.ElapsedTime() >= step.Time * 1000 ? RState.End : RState.Running;
                case StepType.OverEtch:
                    return step.ElapsedTime() >= (step.GetLastEPDStepTime() * step.OverEtchPercent / 100) ? RState.End : RState.Running;
                case StepType.EndPoint:
                    if (step.ElapsedTime() > step.MaxEndPointTime * 1000)
                    {
                        LOG.Write(eEvent.INFO_PROCESS, Chamber.Module, $"Step:{step.StepNo} timeout, did not capture endpoint signal in {step.MaxEndPointTime} seconds");
                        return RState.End;
                    }
                    else
                    {
                        return Chamber.EPDCaptured ? RState.End : RState.Running;
                    }
            }

            return RState.Running;
        }

        private RState stepEnder(RecipeStep step)
        {
            if (step.Type == StepType.EndPoint)
            {
                Chamber.EPDStepStop();
            }
            return RState.End;
        }

        public bool LoadStepFuns(RecipeStep step)
        {
            step.starter = stepStarter;
            step.checker = stepChecker;
            step.ender = stepEnder;
            return true;
        }
    }
}