using Aitex.Core.RT.DataCenter;
using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.RT.OperationCenter;
using Aitex.Core.RT.SCCore;
using Aitex.Core.Util;
using Aitex.Sorter.Common;
using MECF.Framework.Common.Communications;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot.HineAutomation
{
    public class HAtmRobot : Robot
    {
        #region properties
        public override bool Error
        {
            get
            {
                return _exceuteErr;
            }
        }

        public bool IsThetaBusy { get; set; }
        public bool IsZBusy { get; set; }
        public bool IsRadialBusy { get; set; }

        public override bool Busy
        {
            get
            {
                return IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy || (!_motionTimer.IsIdle() && _motionTimer.GetElapseTime() < _motionTime) /*|| ThetaAxisAddressPosition != _targetThetaAxisAddressPosition || ZAxisAddressPosition != _targetZAxisAddressPosition*/;
            }
        }

        public override bool Moving
        {
            get
            {
                return IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy || (!_motionTimer.IsIdle() && _motionTimer.GetElapseTime() < _motionTime) /*|| ThetaAxisAddressPosition != _targetThetaAxisAddressPosition || ZAxisAddressPosition != _targetZAxisAddressPosition*/;
            }
        }

        public override bool WaferOnBlade1 => WaferPresentOnBlade1;

        public bool IsBusy { private get; set; }
        public bool IsRetract { get;   set; }
        public bool IsUp { get;   set; }
        public int ThetaAxisAddressPosition { get; set; }
        public int ZAxisAddressPosition { get; set; }
        public int RetractReqPos { get; set; }
        public int RotateReqPos { get; set; }
        public int ZReqPos { get; set; }
        public int ZActPos { get; set; }
        public string SlotMap { get; set; }
        public Dictionary<string, string> ErrorCodeReference;
        public R_TRIG IsRotationAxisUnreferencedTrig { get; set; }
        public R_TRIG IsExtensionAxisUnreferencedTrig { get; set; }
        public R_TRIG IsZAxisUnreferencedTrig { get; set; }
        public bool IsHomed => _isHomed;
        #endregion

        #region fields
        private HAtmConnection _connection;
        private string _address;
        private PeriodicJob _thread;
        private LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
        private object _lockerHandlerList = new object();

        private R_TRIG _trigError = new R_TRIG();
        private R_TRIG _trigWarningMessage = new R_TRIG();
        private string _lastError = string.Empty;
        private int _errorCode;

        private int _targetThetaAxisAddressPosition;
        private int _targetZAxisAddressPosition;
        private HandlerBase _waferMoveHandler;
        private HandlerBase _homeHandler;
        private bool _isHomed;
        private bool _isSimulator;
        //private bool _isFirstHome = true;
        private bool _enableLog;
        private bool _isPowerUp = true;

        private DeviceTimer _motionTimer = new DeviceTimer();
        private int _motionTime = 1000;
        private Dictionary<string, int> _motionTimeDic;
        private ModuleName _lastTarget;

        private R_TRIG _zAxisHomeTrig = new R_TRIG();
        #endregion


        public HAtmRobot(string module)
            : base(module, module, module, module, "", RobotType.HAtm)
        {
            IsRetract = true;
        }
        static bool CheckAddressPort(string s)
        {
            bool isLegal;
            Regex regex = new Regex(@"^((2[0-4]\d|25[0-5]|[1]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[1]?\d\d?)\:([1-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-9][0-9][0-9][0-9]|[1-6][0-5][0-5][0-3][0-5])$");//CheckAddressPort
            Match match = regex.Match(s);
            if (match.Success)
            {
                isLegal = true;
            }
            else
            {
                isLegal = false;
            }
            return isLegal;
        }
        public override bool Initialize()
        {
            _address = SC.GetStringValue($"{Module}.Address");
            _isSimulator = SC.GetValue<bool>("System.IsSimulatorMode");
            _enableLog = SC.GetValue<bool>($"{Module}.EnableLogMessage");

            _connection = new HAtmConnection(_address);
            if (CheckAddressPort(_address))
            {
                if (_connection.Connect())
                {
                    EV.PostInfoLog(Module, $"{Module} connected");
                }
            }
            else EV.PostWarningLog(Module, $"{Module} Adress is illegal");

            _thread = new PeriodicJob(50, OnTimer, $"{Module} MonitorHandler", true);

            DATA.Subscribe($"{Name}.IsHomed", () => _isHomed);
            DATA.Subscribe($"{Name}.IsConnected", () => _connection.IsConnected);

            OP.Subscribe("Robot.QueryOperationalStatus", (string cmd, object[] args) =>
            {
                QueryOperationalStatus();
                return true;
            });

            _motionTimeDic = new Dictionary<string, int>()
            {
                { $"{ModuleName.Cassette}.{ModuleName.PM}.Picking",4000},
                { $"{ModuleName.PM}.{ModuleName.PM}.Picking",1500},
                { $"{ModuleName.PM}.{ModuleName.Cooling}.Picking",2400},
                { $"{ModuleName.Cooling}.{ModuleName.Cooling}.Picking",1500},
                { $"{ModuleName.Cooling}.{ModuleName.PM}.Picking",2400},
                { $"{ModuleName.Cassette}.{ModuleName.Cooling}.Picking",2200},
                { $"{ModuleName.Cooling}.{ModuleName.Cassette}.Picking",2200},
                { $"{ModuleName.Cassette}.{ModuleName.Cassette}.Picking",1500},
                { $"{ModuleName.PM}.{ModuleName.Cassette}.Picking",4000},
                { $"{ModuleName.TMRobot}.{ModuleName.Cassette}.Picking",5000},
                { $"{ModuleName.TMRobot}.{ModuleName.Cooling}.Picking",3700},
                { $"{ModuleName.TMRobot}.{ModuleName.PM}.Picking",2200},
                { $"System.{ModuleName.Cassette}.Picking",5000},
                { $"System.{ModuleName.Cooling}.Picking",3700},
                { $"System.{ModuleName.PM}.Picking",2200},
            };

            ErrorCodeReference = new Dictionary<string, string>()
            {
                { "S0","Serial response timeout"},
                { "S1","Illegal sc interrupt"},
                { "S2","Parity Error"},
                { "S3","Input Buffer overflow"},
                { "C0","Command not recognized"},
                { "C1","Illegal Z-Axis Command Address"},
                { "C2","Illegal Radial Axis Command Address"},
                { "C3","Illegal Theta Axis Command Address"},
                { "C4","Illegal Pick – wafer on pan"},
                { "C5","Illegal Place – wafer not on pan"},
                { "C6","Illegal action command – error present"},
                { "C7","Command overrun – Hatm5.0 Busy"},
                { "C8","Illegal command – not in learn mode"},
                { "C9","Illegal Search – hardware not present"},
                { "CA","Illegal Fetch – hardware not present"},
                { "CB","Illegal Action – data not valid"},
                { "CC","Illegal Action – Request Queue overrun"},
                { "CD","Illegal Action – Overcurrent Latch Set"},
                { "CE","Illegal Action – Interlock Open"},
                { "CF","Loss of Vacuum Detect"},
                { "D0","Illegal Pitch"},
                { "D1","Illegal Offset"},
                { "D2","Illegal number of slots"},
                { "D3","Illegal rotate position"},
                { "D4","Illegal difference value"},
                { "D5","Parameter missing"},
                { "D6","Illegal Set Command"},
                { "D7","Illegal Option"},
                { "D8","Illegal Category"},
                { "D9","Illegal Bias"},
                { "DA","Illegal Bias Set, Z not valid"},
                { "DB","Invalid rotational speed data(exceeded the legal percent range)"},
                { "DC","Invalid z-axis speed data (exceeded the legal percent range)"},
                { "I0","Z requested position is out of range"},
                { "I1","Theta requested position is out of range"},
                { "I2","Radial requested position is out of range"},
                { "I3","Illegal Z Position"},
                { "I4","Illegal Theta Position"},
                { "I5","Illegal Data"},
                { "A0","Theta Axis action timeout"},
                { "A1","Z-Axis action timeout"},
                { "A2","Radial Axis action timeout"},
                { "A3","Theta overtravel"},
                { "A4","Theta Axis reference detect"},
                { "A5","Z-Axis reference detect"},
                { "A6","Function timeout"},
                { "A7","Loss of Retrace on Rotate"},
                { "A8","Cassette Interlock error"},
                { "A9","Overcurrent shutdown"},
                { "P0","Bad Checksum – Theta Parameters"},
                { "P1","Bad Checksum – Z Parameters"},
                { "P2","Bad Checksum – Radial Parameters"},
                { "F0","Flipper current limit activated"},
                { "F1","Flipper device error"},
                { "F2","Flipper over voltage"},
                { "F3","Flipper over temperature"},
                { "F4","Flipper continuous current limit"},
                { "F5","No Flipper is installed"},
            };

            IsRotationAxisUnreferencedTrig = new R_TRIG();
            IsExtensionAxisUnreferencedTrig = new R_TRIG();
            IsZAxisUnreferencedTrig = new R_TRIG();

            return base.Initialize();
        }

        private bool OnTimer()
        {
            try
            {
                _connection.MonitorTimeout();



                _connection.MonitorConnection(SC.GetValue<int>("TMRobot.ReconnectCount"), out bool retried);

                if (retried)
                {
                    lock (_lockerHandlerList)
                    {
                        _lstHandler.Clear();
                    }
                }
                if (!_connection.IsConnected || _connection.IsCommunicationError)
                {
                    return true;
                }
                if (_connection.IsBusy)
                    return true;

                HandlerBase handler = null;

                lock (_lockerHandlerList)
                {
                    if (_isPowerUp)
                    {
                        if(SC.GetValue<bool>("TMRobot.AllCommandsHaveResponse"))
                            _lstHandler.AddFirst(new SetCommandResponseHandler(this));
                        _isPowerUp = false;
                    }
                    if (_lstHandler.Count == 0)
                    {
                        _lstHandler.AddLast(new QueryOperationalStatusHandler(this));
                        _lstHandler.AddLast(new QueryAllAxisStatusHandler(this));
                        _lstHandler.AddLast(new QueryThetaAxisStatusHandler(this));
                        _lstHandler.AddLast(new QueryZAxisStatusHandler(this));
                        _lstHandler.AddLast(new QueryRadialAxisStatusHandler(this));
                        _lstHandler.AddLast(new QueryPositionHandler(this));
                    }

                    if (_lstHandler.Count > 0)
                    {
                        handler = _lstHandler.First.Value;

                        _lstHandler.RemoveFirst();
                    }
                }

                if (handler != null)
                {
                    handler.SendText = ((HAtmHandler)handler).Package();
                    _connection.Execute(handler);
                }

                if (_waferMoveHandler != null)
                {
                    var pick = _waferMoveHandler as PickHandler;
                    if (pick != null && WaferOnBlade1 && WaferManager.Instance.CheckHasWafer(pick.Target, pick.Slot))
                    {
                        WaferManager.Instance.WaferMoved(pick.Target, pick.Slot, ModuleHelper.Converter(Name), (int)Hand.Blade1);
                        CmdBladeTarget = $"{pick.Target}.Retract";

                    }

                    var place = _waferMoveHandler as PlaceHandler;
                    if (place != null && !WaferOnBlade1 && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Name), (int)Hand.Blade1))
                    {
                        WaferManager.Instance.WaferMoved(ModuleHelper.Converter(Name), (int)Hand.Blade1, place.Target, place.Slot);
                        CmdBladeTarget = $"{place.Target}.Retract";
                    }
                }

                if (_waferMoveHandler != null && !Moving)
                {
                    _lastTarget = ((HAtmHandler)_waferMoveHandler).Target;
                    ((HAtmHandler)_waferMoveHandler).Update();
                    _waferMoveHandler = null;
                    _motionTimer.Stop();
                }

                if (_homeHandler != null)
                {
                    _zAxisHomeTrig.CLK = ZReqPos == 0;
                    if(_zAxisHomeTrig.Q)//means ZAXis is homed
                    {
                        ChangeRobotBladeTarget();
                    }
                    
                    if (!Moving)
                    {
                        _lastTarget = ((HAtmHandler)_homeHandler).Target;
                        _isHomed = true;
                        _homeHandler = null;
                        _motionTimer.Stop();
                    }
                }
            }

            catch (Exception ex)
            {
                LOG.Write(ex);
            }

            return true;
        }

        private void ChangeRobotBladeTarget()
        {
            //CmdBladeTarget = $"{ModuleHelper.Converter(RobotDevice.Name)}.Retract";
            int cassette = 180;
            int cooling = 110;
            int pm = 55;
            if(Math.Abs(RotateReqPos - cassette) < 10)
            {
                CmdBladeTarget = $"{ModuleName.Cassette}.{ModuleHelper.Converter(Name)}.Retract";
                return;
            }

            if (Math.Abs(RotateReqPos - cooling) < 10)
            {
                CmdBladeTarget = $"{ModuleName.Cooling}.{ModuleHelper.Converter(Name)}.Retract";
                return;
            }

            if (Math.Abs(RotateReqPos - pm) < 10)
            {
                CmdBladeTarget = $"{ModuleName.PM}.{ModuleHelper.Converter(Name)}.Retract";
                return;
            }

            if (Math.Abs(RotateReqPos) < 10)
            {
                CmdBladeTarget = $"{ModuleHelper.Converter(Name)}.{ModuleHelper.Converter(Name)}.Retract";
                return;
            }


            CmdBladeTarget = $"{ModuleHelper.Converter(Name)}.Retract";
        }

        public override void Monitor()
        {
            
        }

        public override void Reset()
        {
            _trigError.RST = true;
            _trigWarningMessage.RST = true;
            IsRotationAxisUnreferencedTrig.RST = true;
            IsExtensionAxisUnreferencedTrig.RST = true;
            IsZAxisUnreferencedTrig.RST = true;

            _connection.Reset();

            _exceuteErr = false;

            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new ResetHandler(this));
            }

            _motionTimer.Stop();

            _zAxisHomeTrig.RST = true;

            _isHomed = false;

            base.Reset();
        }

        public void SetErrorCode(int errorCode)
        {
            _errorCode = errorCode;
        }

        public void SetError(string reason)
        {
            _trigWarningMessage.CLK = true;
            if (_trigWarningMessage.Q)
            {
                EV.PostWarningLog(Module, $"{Module} error, {reason}");
                lock (_lockerHandlerList)
                {
                    _lstHandler.AddFirst(new QueryErrorHandler(this));
                }
            }

            _exceuteErr = true;
        }

        public override void OnDataChanged(string package)
        {

        }


        public override bool Home(out string reason)
        {
            reason = string.Empty;
            var handler = new HomeHandler(this);
            //if (_lstHandler.Count > 0 && Moving && !_isFirstHome)
            //{
            //    reason = "Robot busy, please wait or abort.";
            //    EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

            //    return false;
            //}

            SetBusy();

            _exceuteErr = false;
            _targetThetaAxisAddressPosition = 0;
            _targetZAxisAddressPosition = 0;
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
                if(SC.GetValue<bool>("TMRobot.AllCommandsHaveResponse"))
                    _lstHandler.AddFirst(new SetCommandResponseHandler(this));
            }

            _homeHandler = handler;
            _isHomed = false;
            //_isFirstHome = false;

            _enableLog = SC.GetValue<bool>($"{Module}.EnableLogMessage");

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);
            _zAxisHomeTrig.RST = true;

            return true;
        }

        public bool Pick(ModuleName target, int slot, out string reason)
        {
            reason = string.Empty;
            var handler = new PickHandler(this, target, slot);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }
            _waferMoveHandler = handler;

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            if(_isSimulator)
                WaferPresentOnBlade1 = false;

            return true;
        }

        public bool Place(ModuleName target, int slot, out string reason)
        {
            reason = string.Empty;
            var handler = new PlaceHandler(this, target, slot);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            _waferMoveHandler = handler;

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            if (_isSimulator)
                WaferPresentOnBlade1 = true;

            return true;
        }

        public bool GotoExtend(ModuleName target, int slot, bool isPick, bool isUp, out string reason)
        {
            reason = string.Empty;
            var handler = new GotoHandler(this, target, slot, isPick, isUp);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            _waferMoveHandler = handler;

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            return true;
        }

        public bool ZAxisMove(ModuleName target, int slot, bool isUp, out string reason)
        {
            reason = string.Empty;
            var handler = new ZAxisMoveHandler(this, target, slot, isUp);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            IsZBusy = true;
            _motionTimer.Start(0);

            return true;
        }

        public bool PlaceRetract(ModuleName target, int slot, out string reason)
        {
            reason = string.Empty;
            var handler = new PlaceRetractHandler(this, target, slot);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            _waferMoveHandler = handler;

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            return true;
        }

        public bool PickRetract(ModuleName target, int slot, bool isNeedWaferMove, out string reason)
        {
            reason = string.Empty;
            var handler = new PickRetractHandler(this, target, slot, isNeedWaferMove);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            _targetZAxisAddressPosition = RobotConvertor.ChamberSlot2ZAxisPosition(target, slot);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            _waferMoveHandler = handler;

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            return true;
        }

        public void Abort()
        {
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new AbortHandler(this));
            }

            _waferMoveHandler = null;
            _homeHandler = null;
            _motionTimer.Stop();
            _zAxisHomeTrig.RST = true;
        }

        public void QueryAllAxisStatus()
        {
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new QueryAllAxisStatusHandler(this));
            }
        }

        public void QueryError()
        {
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new QueryErrorHandler(this));
            }
        }

        public void SetSpeed()
        {
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new SetThetaSpeedHandler(this, SC.GetValue<int>("TMRobot.Speed"), SC.GetValue<int>("TMRobot.Speed")));
                _lstHandler.AddFirst(new SetReachSpeedHandler(this, SC.GetValue<int>("TMRobot.Speed"), SC.GetValue<int>("TMRobot.Speed")));
            }
        }

        public void QueryOperationalStatus()
        {
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(new QueryOperationalStatusHandler(this));
            }
        }

        public bool VacuumOn(out string reason)
        {
            reason = string.Empty;
            var handler = new VacuumOnHandler(this);
            //if (_lstHandler.Count > 0)
            //{
            //    reason = "Robot busy, please wait or abort.";
            //    EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

            //    return false;
            //}

            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            return true;
        }

        public bool VacuumOff(out string reason)
        {
            reason = string.Empty;
            var handler = new VacuumOffHandler(this);
            //if (_lstHandler.Count > 0)
            //{
            //    reason = "Robot busy, please wait or abort.";
            //    EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

            //    return false;
            //}

            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            return true;
        }

        public bool WaferMap(ModuleName target, out string reason)
        {
            reason = string.Empty;
            var handler = new WaferMapHandler(this, target);
            if (_lstHandler.Count > 0 && Moving)
            {
                reason = "Robot busy, please wait or abort.";
                EV.PostMessage(Name, EventEnum.DefaultWarning, string.Format("{0} {1} {2}", this.Name, handler.Name.ToString(), reason));

                return false;
            }

            SetBusy();

            _targetThetaAxisAddressPosition = RobotConvertor.Chamber2ThetaAxisPosition(target);
            ThetaAxisAddressPosition = -1;
            ZAxisAddressPosition = -1;
            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
            _motionTimer.Start(0);

            return true;
        }

        public bool GetWaferMap(ModuleName target, out string reason)
        {
            reason = string.Empty;
            var handler = new QueryWaferMapHandler(this, target);
            SlotMap = string.Empty;

            lock (_lockerHandlerList)
            {
                _lstHandler.AddFirst(handler);
            }

            return true;
        }

        private void SetBusy()
        {
            //IsBusy || IsThetaBusy || IsZBusy || IsRadialBusy
            IsBusy = true;
            IsThetaBusy = true;
            IsZBusy = true;
            IsRadialBusy = true;
        }

    }
}
