using Aitex.Core.Common;
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 MECF.Framework.Common.Communications;
using MECF.Framework.Common.Equipment;
using MECF.Framework.Common.SubstrateTrackings;
using MECF.Framework.RT.EquipmentLibrary.Core.Extensions;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.RobotBase;
using MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.Sunway.Errors;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading;

namespace MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robots.Sunway
{
    public class SunwayRobot : RobotBaseDevice, IConnection
    {
        #region Variables

        public object _locker = new object();

        public PeriodicJob _thread;

        public readonly Dictionary<string, string> _errorCodeReferenceDic = new Dictionary<string, string>();
        public readonly LinkedList<HandlerBase> _lstHandler = new LinkedList<HandlerBase>();
        public readonly SCConfigItem _scHomeTimeout;
        public readonly SCConfigItem _scMotionTimeout;
        public readonly R_TRIG _trigCommunicationError = new R_TRIG();
        public readonly R_TRIG _trigRetryConnect = new R_TRIG();

        public List<ModuleName> _disabledIntlkModules = new List<ModuleName>();

        public readonly bool _enableLog;
        public string _scRoot;

        public readonly R_TRIG _trigError = new R_TRIG();
        public bool _isAlarm;

        #endregion

        #region Constructors

        public SunwayRobot(string module, string name, string endof = "\r\n") : base(module, name)
        {
            DATA.Subscribe($"{Module}.IsConnected", () => IsConnected);
            DATA.Subscribe($"{Module}.Address", () => Address);
            DATA.Subscribe($"{Module}.IsBobotReady", () => IsReady());
            OP.Subscribe($"{Module}.Reconnect", (string cmd, object[] args) =>
            {
                Disconnect();
                Connect();
                return true;
            });

            OP.Subscribe($"{Module}.STAT", (string cmd, object[] args) =>
            {
                RobotCheckStat();
                return true;
            });

            OP.Subscribe($"{Module}.ERR", (string cmd, object[] args) =>
            {
                RobotCheckError();
                return true;
            });

            OP.Subscribe($"{Module}.MAP", (string cmd, object[] args) =>
            {
                RobotMap(args);
                return true;
            });

            OP.Subscribe($"{Module}.HOME", (string cmd, object[] args) =>
            {
                RobotHome();
                return true;
            });

            OP.Subscribe($"{Module}.PUTSP", (string cmd, object[] args) =>
            {
                RobotPlaceSP(args);
                return true;
            });
            OP.Subscribe($"{Module}.GETSP", (string cmd, object[] args) =>
            {
                RobotPickSP(args);
                return true;
            });
            OP.Subscribe($"{Module}.InputA", (string cmd, object[] args) =>
            {
                InputA();
                return true;
            });

            OP.Subscribe($"{Module}.GETA", (string cmd, object[] args) =>
            {
                RobotPickA(args);
                return true;
            });
            OP.Subscribe($"{Module}.PUTA", (string cmd, object[] args) =>
            {
                RobotPlaceA(args);
                return true;
            });
            OP.Subscribe($"{Module}.GETB", (string cmd, object[] args) =>
            {
                RobotPickB(args);
                return true;
            });
            OP.Subscribe($"{Module}.PUTB", (string cmd, object[] args) =>
            {
                RobotPlaceB(args);
                return true;
            });
            OP.Subscribe($"{Module}.RobotConnectHomeAll", (string cmd, object[] args) =>
            {
                RobotConnectHomeAll();
                return true;
            });
            OP.Subscribe($"{Module}.RESP", (string cmd, object[] args) =>
            {
                RobotRESP();
                return true;
            });
            OP.Subscribe($"{Module}.REMS", (string cmd, object[] args) =>
            {
                RobotREMS();
                return true;
            });
            OP.Subscribe($"{Module}.SVON", (string cmd, object[] args) =>
            {
                RobotSVON();
                return true;
            });
            OP.Subscribe($"{Module}.AbortAction", (string cmd, object[] args) =>
            {
                fAbort(args);
                OnActionDone(args);
                return true;
            });
            //开真空
            OP.Subscribe($"{Module}.VacuumOn", (string cmd, object[] args) =>
            {
                RobotVacuumOn();
                return true;
            });
            //关真空
            OP.Subscribe($"{Module}.VacuumOff", (string cmd, object[] args) =>
            {
                RobotVacuumOff();
                return true;
            });
            //开夹爪
            OP.Subscribe($"{Module}.HandOn", (string cmd, object[] args) =>
            {
                RobotGripOff();
                return true;
            });
            //关夹爪
            OP.Subscribe($"{Module}.HandOff", (string cmd, object[] args) =>
            {
                RobotGripOn();
                return true;
            });


            ModuleAssociateStationDic = new Dictionary<string, int>()
            {
                {$"{ModuleName.PM1 }", 1 },
                {$"{ModuleName.PM2}", 2 },
                {$"{ModuleName.Buffer}1", 3},
                {$"{ModuleName.Buffer}2", 4},
                {$"{ModuleName.Buffer}3", 5},
                {$"{ModuleName.Load}", 6},
                {$"{ModuleName.LoadLock}", 6},
                {$"{ModuleName.UnLoad}", 7},
                {$"{ModuleName.Aligner}", 8},
                {$"{ModuleName.CassAL}", 9},
                {$"{ModuleName.CassAR}", 10},
                {$"{ModuleName.CassBL}", 12},
            };


            try
            {
                string deviceIP = "";
                deviceIP = SC.GetStringValue($"{Module}.Address");
                _enableLog = SC.GetValue<bool>($"{Module}.EnableLogMessage");
                _scHomeTimeout = SC.GetConfigItem($"{Module}.HomeTimeout");
                _scMotionTimeout = SC.GetConfigItem($"{Module}.MotionTimeout");

                WaferManager.Instance.SubscribeLocation(Module, 1);

                Connection = new SunwayRobotTCPConnection(deviceIP, endof);
                Connection.EnableLog(_enableLog);

                Status = new SunwayRobotStatus();

                if (Connection.Connect())
                {
                    _trigConnection.CLK = true;
                    PortStatus = "Open";
                    EV.PostInfoLog(Module, $"{Module}.{Name} connected");
                }
                else
                {
                    PortStatus = "Close";
                    EV.PostInfoLog(Module, $"{Module}.{Name} connect failed");
                }

                _thread = new PeriodicJob(100, OnTimer, $"{Module}.{Name} MonitorHandler", true);
            }
            catch (Exception ex)
            {
                EV.PostAlarmLog(Module, ex.ToString());
            }
        }

        #endregion

        #region Properties

        public string Address => Connection.Address;

        public bool IsConnected => Connection.IsConnected && !Connection.IsCommunicationError;

        public string PortStatus { get; set; } = "Closed";

        public bool Connect() { return Connection.Connect(); }

        public bool Disconnect() { return Connection.Disconnect(); }

        public SunwayRobotTCPConnection Connection { get; }

        public Dictionary<string, int> ModuleAssociateStationDic { get; set; }

        public R_TRIG _trigConnection = new R_TRIG();

        public SunwayRobotStatus Status { get; private set; }

        public SunwayRobotAggregatedErrors Errors { get; private set; }

        #endregion

        #region Methods
        private void CheckStateThenDo(Action onCheckSucceed, Action onCheckFailed = null)
        {
            //// 检查Robot状态
            //_lstHandler.AddLast(new SunwayRobotERRHandler(this, onHandlerEndTask: () =>
            //{
            //    if (Errors.AggregateErrorMessages != null && Errors.AggregateErrorMessages.Count > 0)
            //    {
            //        try
            //        {
            //            onCheckFailed?.Invoke();
            //        }
            //        catch (Exception ex)
            //        {
            //            EV.PostWarningLog(Module, "onCheckFailed action error");
            //            LOG.Error(ex.Message);
            //        }
            //    }
            //    else
            //    {
            //        try
            //        {
            //            onCheckSucceed?.Invoke();
            //        }
            //        catch (Exception ex)
            //        {
            //            EV.PostWarningLog(Module, "onCheckSucceed action error");
            //            LOG.Error(ex.Message);
            //        }
            //    }
            //}));
        }
        public override bool IsReady()
        {
            return !Connection.IsBusy && _lstHandler.Count == 0 && !Connection.IsCommunicationError && !IsBusy;// && !_isAlarm;//&& (RobotState == RobotStateEnum.Idle)
        }

        protected override bool Init()
        {
            return true;
        }

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

                if (!Connection.IsConnected || Connection.IsCommunicationError)
                {
                    lock (_locker)
                    {
                        _lstHandler.Clear();
                    }

                    _trigRetryConnect.CLK = !Connection.IsConnected;
                    if (_trigRetryConnect.Q)
                    {
                        if (!Connection.Connect())
                        {
                            EV.PostAlarmLog(Module, $"Can not connect with {Connection.Address}, {Module}.{Name}");
                        }
                        else
                        {
                            _trigConnection.CLK = true;
                            EV.PostInfoLog(Module, $"Retry connect succee with {Connection.Address}, {Module}.{Name}");

                        }
                    }
                    return true;
                }

                HandlerBase handler = null;
                if (!Connection.IsBusy)
                {
                    lock (_locker)
                    {

                        if (_lstHandler.Count > 0)
                        {
                            Debug.WriteLine($"[Thread {Thread.CurrentThread.ManagedThreadId}] Handler Count before: {_lstHandler.Count}");
                            Debug.WriteLine($"Connection Busy = {Connection.IsBusy}");

                            handler = _lstHandler.First.Value;

                            _lstHandler.RemoveFirst();

                            Debug.WriteLine($"[Thread {Thread.CurrentThread.ManagedThreadId}] Handler Removed: {handler?.GetType().FullName}");
                            Debug.WriteLine($"[Thread {Thread.CurrentThread.ManagedThreadId}] Handler Count after: {_lstHandler.Count}");
                        }
                    }

                    if (handler != null)
                    {
                        Debug.WriteLine($"[Thread {Thread.CurrentThread.ManagedThreadId}] Executing Handler: {handler?.GetType().FullName}");
                        Connection.Execute(handler);
                        Debug.WriteLine($"Connection Busy = {Connection.IsBusy}");
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
            }

            return true;
        }

        public override void Monitor()
        {
            try
            {
                _trigCommunicationError.CLK = Connection.IsCommunicationError;
                if (_trigCommunicationError.Q)
                {
                    EV.PostAlarmLog(Module, $"{Module}.{Name} communication error, {Connection.LastCommunicationError}");
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
            }

        }

        protected override void SubscribeWaferLocation()
        {
            //do nothing
        }

        public override void Reset()
        {
            _trigError.RST = true;

            Connection.SetCommunicationError(false, "");
            _trigCommunicationError.RST = true;
            _trigWarningMessage.RST = true;
            _trigRetryConnect.RST = true;

            base.Reset();
        }

        #endregion

        #region Command Functions
        internal bool PraseGetWaferData()
        {
            if (CurrentParamter != null && CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return false;
                }

                if (!WaferManager.Instance.CheckHasTray(RobotModuleName, 0))
                {
                    WaferManager.Instance.WaferMoved(sourceModule, sourceSlot, RobotModuleName, 0);
                    return true;
                }

            }
            return false;

        }

        /// <summary>
        /// 解析STAT指令返回值。
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        public virtual bool ParseStatusData(string response)
        {
            try
            {
                if (!int.TryParse(response, out var status))
                {
                    EV.PostAlarmLog(Module, $"Incorrect format of STA Response, {response}");
                    return false;
                }

                var stat = status.ToBitTypeClass<SunwayRobotStatus>(4);
                Status = stat;
                var sInfo = Status.AggregateErrorMessages();
                if (sInfo != null)
                {
                    foreach (var s in sInfo)
                    {
                        EV.PostWarningLog(Module, s);
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                EV.PostWarningLog(Module, $"{nameof(ParseStatusData)}() excepted, {ex.Message}");
                return false;
            }

        }

        /// <summary>
        /// 从控制器获取错误代码。
        /// <para>注意：如果控制器返回的字符串格式错误，则解析失败，Errors设置为null。</para>
        /// </summary>
        /// <param name="response"></param>
        /// <returns></returns>
        internal virtual bool ParseErrData(string response)
        {
            try
            {
                if (SunwayRobotAggregatedErrors.IsErrResponse(response, out _) == false)
                {
                    EV.PostAlarmLog(Module, $"Incorrect format of ERR Response, {response}");
                }
                else
                {
                    Errors = null;
                    Errors = new SunwayRobotAggregatedErrors(response);
                    if (Errors.AggregateErrorMessages.Count > 0)
                    {
                        foreach (string errMsg in Errors.AggregateErrorMessages)
                        {
                            EV.PostAlarmLog(Module, errMsg);
                        }
                    }
                }

                return true;
            }
            catch (Exception ex)
            {
                return true;
            }
        }

        internal bool PrasePutWaferData()
        {
            if (CurrentParamter != null && CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return false;
                }

                if (!WaferManager.Instance.CheckHasTray(sourceModule, sourceSlot))
                {
                    WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourceModule, sourceSlot);
                    return true;
                }
            }
            return false;
        }

        public virtual void RobotPickB(object[] args)
        {
            if (args.Length >= 2)
            {
                lock (_locker)
                {
                    _lstHandler.Clear();
                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotGETBHandler(this, args[0].ToString(), Convert.ToInt32(args[1])));
                    });
                }
            }
        }

        public virtual void RobotPlaceB(object[] args)
        {
            if (args.Length >= 2)
            {
                lock (_locker)
                {
                    _lstHandler.Clear();
                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotPUTBHandler(this, args[0].ToString(), Convert.ToInt32(args[1])));
                    });

                }
            }
        }

        public void RobotPickA(object[] args)
        {
            if (args.Length >= 2)
            {

                lock (_locker)
                {
                    _lstHandler.Clear();

                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotGETAHandler(this, args[0].ToString(),
                            Convert.ToInt32(args[1])));
                    });

                }
            }
        }

        public void RobotPlaceA(object[] args)
        {
            if (args.Length >= 2)
            {

                lock (_locker)
                {
                    _lstHandler.Clear();
                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotPUTAHandler(this, args[0].ToString(),
                            Convert.ToInt32(args[1])));
                    });

                }
            }
        }

        public virtual void RobotPickSP(object[] args)
        {
            if (args.Length >= 3)
            {
                lock (_locker)
                {
                    _lstHandler.Clear();
                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotGETSPHandler(this, args[0].ToString(),
                            Convert.ToInt32(args[1]), Convert.ToInt32(args[2])));
                    });

                }
            }
        }

        public void RobotPlaceSP(object[] args)
        {
            if (args.Length >= 3)
            {

                lock (_locker)
                {
                    _lstHandler.Clear();
                    CheckStateThenDo(() =>
                    {
                        _lstHandler.AddLast(new SunwayRobotPUTSPHandler(this, args[0].ToString(),
                            Convert.ToInt32(args[1]), Convert.ToInt32(args[2])));
                    });

                }
            }
        }

        public virtual void SetWaferData(string data)
        {
            //0:无片 1:单片 2:叠片  3:跨槽 ?:未知
            string errorMessage = "";
            int count = 1;
            if (CurrentInteractModule == ModuleName.CassAL || CurrentInteractModule == ModuleName.CassAR)
            {
                count = 25;
            }

            if (CurrentInteractModule == ModuleName.CassBL)
            {
                count = 8;
            }

            for (int i = 0; i < count; i++)
            {
                WaferManager.Instance.DeleteWafer(CurrentInteractModule, i);
            }

            if (data.Length == 53)//Wafer Cassette
            {
                data = data.Replace("MAP", "").Trim().Replace(" ", "");
                for (int i = 0; i < count; i++)
                {
                    string waferStatue = data.Substring(i, 1);
                    if (waferStatue == "1")
                    {
                        if (!WaferManager.Instance.CheckHasWafer(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.CreateWafer(CurrentInteractModule, i, WaferStatus.Normal);
                        }
                    }
                    else if (waferStatue == "0" || waferStatue == "?")
                    {
                        if (WaferManager.Instance.CheckHasWafer(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.DeleteWafer(CurrentInteractModule, i);
                        }
                    }
                    else
                    {
                        string msg = "";
                        if (!WaferManager.Instance.CheckHasWafer(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.CreateWafer(CurrentInteractModule, i, GetWaferStarusByNum(waferStatue, out msg));
                        }
                        else
                        {
                            WaferManager.Instance.GetWafer(CurrentInteractModule, i).WaferStatus = GetWaferStarusByNum(waferStatue, out msg);// Aitex.Core.Common.WaferStatus.Crossed;
                        }
                        errorMessage += $"slot {i + 1} has {msg}!" + "\r\n";
                    }
                }
            } //Wafer Cassette
            else if (data.Length == 19)//Tray Cassette
            {
                data = data.Replace("MAP", "").Trim().Replace(" ", "");
                for (int i = 0; i < count; i++)
                {
                    string tryaStatue = data.Substring(i, 1);
                    if (tryaStatue == "1")
                    {
                        if (!WaferManager.Instance.CheckHasTray(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.CreateTray(CurrentInteractModule, i);
                        }
                    }
                    else if (tryaStatue == "0" || tryaStatue == "?")
                    {
                        if (WaferManager.Instance.CheckHasTray(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.DeleteWafer(CurrentInteractModule, i);
                        }
                    }
                    else
                    {
                        if (!WaferManager.Instance.CheckHasTray(CurrentInteractModule, i))
                        {
                            WaferManager.Instance.CreateTray(CurrentInteractModule, i, Aitex.Core.Common.TrayStatus.Crossed);
                        }
                        errorMessage += $"slot {i + 1} has crossed wafer!" + "\r\n";
                    }
                }
            }
            else 
            {
                if (data.Contains("LOAD A ON"))
                {
                    if (Module=="WaferRobot" && !WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Module), 0))
                    {
                        WaferManager.Instance.CreateWafer(ModuleHelper.Converter(Module), 0, WaferStatus.Normal);
                    }

                    if (Module == "TrayRobot" && !WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(Module), 0))
                    {
                        WaferManager.Instance.CreateTray(ModuleHelper.Converter(Module), 0, TrayStatus.Normal);
                    }
                }
                else if (data.Contains("LOAD A OFF"))
                {
                    if (Module == "WaferRobot" && WaferManager.Instance.CheckHasWafer(ModuleHelper.Converter(Module), 0))
                    {
                        WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Module), 0);
                    }

                    if (Module == "TrayRobot" && WaferManager.Instance.CheckHasTray(ModuleHelper.Converter(Module), 0))
                    {
                        WaferManager.Instance.DeleteWafer(ModuleHelper.Converter(Module), 0);
                    }
                }
            }

            if (!String.IsNullOrEmpty(errorMessage))
            {
                EV.PostWarningLog(Module, $"Module {CurrentInteractModule} {errorMessage}");
            }
        }

        //0:无片 1:单片 2:叠片  3:跨槽 ?:未知
        private WaferStatus GetWaferStarusByNum(string num, out string msg)
        {
            switch (num)
            {
                case "2":
                    msg = "crossed";
                    return WaferStatus.Crossed;
                case "3":
                    msg = "double";
                    return WaferStatus.Double;
                case "?":
                    msg = "unknow";
                    return WaferStatus.Double;
                default:
                    msg = "crossed";
                    return WaferStatus.Crossed;
            }
        }

        public void RobotCheckStat()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotSTATHandler(this));
            }
        }

        public virtual void RobotCheckError()
        {
            lock (_locker)
            {
                _lstHandler.Clear();
                _lstHandler.AddLast(new SunwayRobotERRHandler(this));
            }
        }

        public void RobotHome()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotHomeHandler(this));
            }
        }

        public void RobotMap(object[] args)
        {
            lock (_locker)
            {
                _lstHandler.Clear();
                _lstHandler.AddLast(new SunwayRobotGotoMapHandler(this, args[0].ToString(),false));
                CheckStateThenDo(() => { _lstHandler.AddLast(new SunwayRobotMapHandler(this, args[0].ToString())); });
            }
        }

        public virtual void InputA()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotOutpOpenHandler(this));
                _lstHandler.AddLast(new SunwayRobotINPUTHandler(this));
                _lstHandler.AddLast(new SunwayRobotOutpCloseHandler(this));
            }
        }


        public virtual void RobotConnectHomeAll()
        {
            IsBusy = false;
            Connection.ForceClear();
            _lstHandler.Clear();
            lock (_locker)
            {
                //Robot Home指令包含了清除报警，电机使能，Home动作
                _lstHandler.AddLast(new SunwayRobotSetEchoHandler(this, false));
                _lstHandler.AddLast(new SunwayRobotHomeHandler(this, _scMotionTimeout.IntValue));
                _lstHandler.AddLast(new SunwayRobotRQLoadHandler(this));
            }
        }

        public void RobotRESP()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotRespHandler(this));
            }
        }

        public void RobotREMS()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotRemsHandler(this));
            }
        }

        public void RobotSVON()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotSVONHandler(this));
            }
        }

        public void RobotVacuumOn()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotVacHandler(this,true,RobotArmEnum.Blade1));
            }
        }

        public void RobotVacuumOff()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotVacHandler(this, false, RobotArmEnum.Blade1));
            }
        }

        public void RobotGripOn()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotGripHandler(this, true, RobotArmEnum.Blade1));
            }
        }

        public void RobotGripOff()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotGripHandler(this, false, RobotArmEnum.Blade1));
            }
        }

        public void RobotHandOn()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotBOPTPHandler(this));
            }
        }

        public void RobotHandOff()
        {
            _lstHandler.Clear();
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotBOPTClosePHandler(this));
            }
        }
        #endregion

        #region Note Functions
        public readonly R_TRIG _trigWarningMessage = new R_TRIG();
        ///<summary>
        /// 查询并打印错误
        ///</summary>
        ///<param name = eason">当前指令的错误原因: 超时或返回? </param>
        ///<param name = erformErrCmd">是否执行ERR指令</param>
        ///<para>如果是E[指令本身返回“?，则不要再执行ERR指令，以免造成死循环。</para>
        public void NoteError(string reason, bool performErrCmd = true)
        {
            //确保传入的信息不能为空
            if (string.IsNullOrEmpty(reason))
                reason = "Unknown Error";

            //重置TCPConnection对象，否则RobotCheckError函数中添加ERR指令到命令列队会造成TCPConnection失效
            fAbort(null);
            EV.PostAlarmLog(Module, $"{Module}.{Name} error, {reason}");


            // 查询机械手异常信息。
            //if (performErrCmd)// 如果是ERR指令本身返回?，则不要再执行ERR指令，以免造成死循环
            //    RobotCheckError();


            //             if (reason != null)
            //             {
            //                 fAbort(null);
            // 
            //                 _trigWarningMessage.CLK = true;
            //                 var content = reason;
            //                 if (_errorCodeReferenceDic.ContainsKey(reason))
            //                 {
            //                     content = _errorCodeReferenceDic[reason];
            //                 }
            //                 if (_trigWarningMessage.Q)
            //                 {
            //                     EV.PostWarningLog(Module, $"{Module}.{Name} error, {reason} {content}");
            //                 }
            //                 _isAlarm = true;
            //                 ErrorCode = reason;
            //             }
            //             else
            //             {
            //                 _isAlarm = false;
            //             }
        }

        public virtual void NoteActionCompleted()
        {
            //Blade1Target = ModuleName.System;
            //Blade2Target = ModuleName.System;
            IsBusy = false;
            CheckToPostMessage((int)RobotMsg.ActionDone);
        }

        internal void NotePickCompleted()
        {
            PostMessageWithoutCheck((int)RobotMsg.PickComplete, CurrentParamter);
        }

        internal void NotePlaceCompleted()
        {
            PostMessageWithoutCheck((int)RobotMsg.PlaceComplete, CurrentParamter);
        }

        protected override bool fStartHome(object[] param)
        {
            lock (_locker)
            {
                _lstHandler.AddLast(new SunwayRobotHomeHandler(this, _scHomeTimeout.IntValue));
            }
            return true;
        }

        protected override bool fClear(object[] param)
        {
            return true;
        }

        public override bool ReadParameter(object[] param)
        {
            return CheckToPostMessage((int)RobotMsg.ReadData, param);
        }

        protected override bool fStartReadData(object[] param)
        {
            return true;
        }

        protected override bool fStartSetParameters(object[] param)
        {
            return true;
        }

        protected override bool fStartTransferWafer(object[] param)
        {
            return true;
        }

        protected override bool fStartUnGrip(object[] param)
        {
            return true;
        }

        protected override bool fStartGrip(object[] param)
        {
            return true;
        }

        protected override bool fStartGoTo(object[] param)
        {
            return true;
        }

        protected override bool fStartMapWafer(object[] param)
        {
            try
            {
                if (param.Length >= 1)
                {
                    lock (_locker)
                    {
                        _lstHandler.AddLast(new SunwayRobotGotoMapHandler(this, param[0].ToString(), false));
                        _lstHandler.AddLast(new SunwayRobotMapHandler(this, param[0].ToString(), _scMotionTimeout.IntValue));
                        _lstHandler.AddLast(new SunwayRobotRSRHandler(this, param[0].ToString(), _scMotionTimeout.IntValue));
                        _lstHandler.AddLast(new SunwayRobotGotoMapHandler(this, param[0].ToString(), true));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        protected override bool fStartSwapWafer(object[] param)
        {
            return false;
        }

        

       

        protected override bool fPlaceComplete(object[] param)
        {
            //arm, station, slot

            Blade1Target = ModuleName.System;
            Blade2Target = ModuleName.System;

            if (CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return false;
                }

                if (RobotModuleName == ModuleName.WaferRobot)
                {
                    if (WaferManager.Instance.CheckHasWafer(RobotModuleName, 0))
                    {
                        WaferManager.Instance.WaferMoved(RobotModuleName, 0, sourceModule, sourceSlot);
                    }
                }
                else
                {
                    if (WaferManager.Instance.CheckHasTray(RobotModuleName, 0))
                    {
                        WaferManager.Instance.TrayMoved(RobotModuleName, 0, sourceModule, sourceSlot);
                    }
                }

            }

            return base.fPlaceComplete(param);
        }

        protected override bool fPickComplete(object[] param)
        {
            //arm, station, slot

            Blade1Target = ModuleName.System;
            Blade2Target = ModuleName.System;

            if (CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return false;
                }

                if (RobotModuleName == ModuleName.WaferRobot)
                {
                    if (WaferManager.Instance.CheckHasWafer(sourceModule, sourceSlot))
                    {
                        WaferManager.Instance.WaferMoved(sourceModule, sourceSlot, RobotModuleName, 0);
                    }
                }
                else
                {
                    if (WaferManager.Instance.CheckHasTray(sourceModule, sourceSlot))
                    {
                        WaferManager.Instance.TrayMoved(sourceModule, sourceSlot, RobotModuleName, 0);
                    }
                }

                //lock (_locker)
                //{
                //    CheckStateThenDo(() =>
                //    {
                //        _lstHandler.AddLast(new SunwayRobotGETSPHandler(this, CurrentParamter[1].ToString(), Convert.ToInt32(CurrentParamter[2]), 4, _scMotionTimeout.IntValue)); //缩回
                //    });
                //}
            }

            return base.fPickComplete(param);
        }

        protected override bool fResetToReady(object[] param)
        {
            return true;
        }

        protected override bool fReset(object[] param)
        {
            _trigError.RST = true;

            Connection.SetCommunicationError(false, "");
            _trigCommunicationError.RST = true;

            _trigRetryConnect.RST = true;
            if (_isAlarm)
            {
                lock (_locker)
                {
                    //_lstHandler.AddLast(new SunwayRobotResetHandler(this));
                }

                Thread.Sleep(100);
                CheckToPostMessage((int)RobotMsg.ActionDone);
            }

            IsBusy = false;

            return true;
        }

        protected override bool fMonitorReset(object[] param)
        {
            IsBusy = false;
            return true;
        }

        protected override bool fStartInit(object[] param)
        {
            RobotConnectHomeAll();
            return true;
        }

        protected override bool fError(object[] param)
        {
            return true;
        }

        //[module][slot]  伸出手臂
        protected override bool fStartExtendForPick(object[] param)
        {
            try
            {
                if (param.Length >= 3)
                {
                    lock (_locker)
                    {
                        //初始位置和伸出
                        int slot = Convert.ToInt32(param[2]) + 1;
                        _lstHandler.AddLast(new SunwayRobotGotoHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, true, true, _scMotionTimeout.IntValue));
                        _lstHandler.AddLast(new SunwayRobotPickHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, false, _scMotionTimeout.IntValue));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        //(module, slot)
        protected override bool fStartPickWafer(object[] param)
        {
            try
            {
                //arm, station, slot
                if (param.Length >= 3)
                {
                    lock (_locker)
                    {
                        int slot = Convert.ToInt32(param[2]) + 1;
                        _lstHandler.AddLast(new SunwayRobotPickHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, true, _scMotionTimeout.IntValue));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        protected override bool fStartExtendForPlace(object[] param)
        {
            try
            {
                if (param.Length >= 3)
                {
                    lock (_locker)
                    {
                        //初始位置和伸出
                        int slot = Convert.ToInt32(param[2]) + 1;
                        _lstHandler.AddLast(new SunwayRobotGotoHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, true, false, _scMotionTimeout.IntValue));
                        _lstHandler.AddLast(new SunwayRobotPlaceHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, false, _scMotionTimeout.IntValue));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        //(module, slot)
        protected override bool fStartPlaceWafer(object[] param)
        {
            try
            {
                //arm, station, slot
                if (param.Length >= 3)
                {
                    lock (_locker)
                    {
                        // 执行Place指令
                        int slot = Convert.ToInt32(param[2]) + 1;
                        _lstHandler.AddLast(new SunwayRobotPlaceHandler(this, param[1].ToString(), slot, RobotArmEnum.Blade1, true, _scMotionTimeout.IntValue));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        /// <summary>
        /// 开始从Pick处缩回
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        protected override bool fStartRetractFromPick(object[] param)
        {
            try
            {
                if (param.Length >= 2)
                {

                    lock (_locker)
                    {
                        CheckStateThenDo(() =>
                        {
                            _lstHandler.AddLast(new SunwayRobotPUTSPHandler(this, param[0].ToString(),
                                Convert.ToInt32(param[1]), 3, _scMotionTimeout.IntValue));
                            _lstHandler.AddLast(new SunwayRobotPUTSPHandler(this, param[0].ToString(),
                                Convert.ToInt32(param[1]), 4, _scMotionTimeout.IntValue));

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

            return true;
        }

        /// <summary>
        /// 开始从Place处缩回
        /// </summary>
        /// <param name="param"></param>
        /// <returns></returns>
        protected override bool fStartRetractFromPlace(object[] param)
        {
            try
            {
                if (param.Length >= 2)
                {
                    lock (_locker)
                    {
                        _lstHandler.AddLast(new SunwayRobotPUTSPHandler(this, param[0].ToString(), Convert.ToInt32(param[1]), 3, _scMotionTimeout.IntValue));
                        _lstHandler.AddLast(new SunwayRobotPUTSPHandler(this, param[0].ToString(), Convert.ToInt32(param[1]), 4, _scMotionTimeout.IntValue));
                    }
                }
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        protected override bool fStartExecuteCommand(object[] param)
        {
            try
            {
                InputA();
            }
            catch (Exception ex)
            {
                LOG.Write(ex);
                return false;
            }

            return true;
        }

        public override RobotArmWaferStateEnum GetWaferState(RobotArmEnum arm)
        {
            if (arm == RobotArmEnum.Blade1)
            {
                return IsWaferPresenceOnBlade1 ? RobotArmWaferStateEnum.Present : RobotArmWaferStateEnum.Absent;
            }

            return RobotArmWaferStateEnum.Unknown;
        }

        protected override bool fStop(object[] param)
        {
            lock (_locker)
            {
                IsBusy = false;
                Connection.ForceClear();
                _lstHandler.Clear();
            }
            return true;
        }

        protected override bool fAbort(object[] param)
        {
            lock (_locker)
            {
                IsBusy = false;
                Connection.ForceClear();
                _lstHandler.Clear();
            }
            return true;
        }

        #endregion

        internal void GetWaferData()
        {
            Blade1Target = ModuleName.System;
            Blade2Target = ModuleName.System;
            IsBusy = false;
            if (CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot = 0;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return;
                }
                if (WaferManager.Instance.CheckNoTray(RobotModuleName, 0) && WaferManager.Instance.CheckHasTray(sourceModule, sourceSlot))
                {
                    WaferManager.Instance.TrayMoved(sourceModule, sourceSlot, RobotModuleName, 0);
                }
            }
        }

        internal void PutWaferData()
        {
            Blade1Target = ModuleName.System;
            Blade2Target = ModuleName.System;
            IsBusy = false;
            if (CurrentParamter.Length >= 3)
            {
                ModuleName sourceModule;
                int sourceSlot = 0;
                if (!int.TryParse(CurrentParamter[2].ToString(), out sourceSlot) || !Enum.TryParse(CurrentParamter[1].ToString(), out sourceModule))
                {
                    return;
                }
                if (WaferManager.Instance.CheckHasTray(RobotModuleName, 0) && WaferManager.Instance.CheckNoTray(sourceModule, sourceSlot))
                {
                    WaferManager.Instance.TrayMoved(RobotModuleName, 0, sourceModule, sourceSlot);
                }
            }
        }
    }
}
