using Aitex.Core.Common;
using Aitex.Core.RT.Device;
using Aitex.Core.RT.Log;
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 System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Venus_Core;
using Venus_RT.Devices.EFEM;
using Venus_RT.Devices.TM;
using Venus_RT.Modules;
namespace Venus_RT.Devices.VCE
{
    /// 
    /// 素珀 vce 驱动
    /// 
    public class SunWayVce : VCEModuleBase
    {
        #region 私有变量
        private AsyncSerialPort _serialport;
        private string _portname;
        private string _newline = "\r\n";//终止符 0D 0A
        private object _locker = new object();
        private bool _IsAsciiMode;
        private LinkedList _lstAsciiMsgs = new LinkedList();
        private PeriodicJob _thread;
        private Regex _match_ReadMsg = new Regex(@"X,.*");
        private Regex _matchErrorCode = new Regex(@"(?<=_ERR,)(.*)");
        private ModuleName _moduleName;
        private RState _status;
        private string _currentMsg;
        private VceMessage _currentVceMessage;
        private bool _HasReceiveMsg;
        private bool _IsDashWaferError;
        private int _currentSlot = 0;
        public override int CurrentSlot => _currentSlot;
        private ModuleName _baseLPIndex
        {
            get
            {
                switch (RtInstance.ConfigType)
                {
                    case ConfigType.VenusSE:
                        return ModuleName.LP1;
                    case ConfigType.VenusDE:
                        return _moduleName == ModuleName.VCEA ? ModuleName.LP1 : ModuleName.LP2;
                    default:
                        return ModuleName.System;
                }
            }
        }
        private Loadport[] _LPMs = new Loadport[1];
        public override ILoadport this[ModuleName mod]
        {
            get
            {
                if (!ModuleHelper.IsLoadPort(mod))
                    throw new ApplicationException($"{mod} is NOT Loadport");
                return _LPMs[mod - _baseLPIndex];
            }
        }
        //待补充
        private Dictionary _ErrorCode2Reason = new Dictionary()
        {
            {"221","错误的 ARM 参数" },
            {"233","伸缩信号未使能" },
            {"304","未识别的错误码" },
            {"305","未识别的指令" },
            {"309","不支持的指令" },
            {"401","ZWAFER 参数错误" },
            {"402","非法的 slot 参数" },
            {"403","运动指令 RX 参数错误" },
            {"404","晶圆夹取失败" },
            {"405","晶圆释放失败" },
            {"406","气缸压力表检测错误" },
            {"407","Mapping 传感器伸出失败" },
            {"408","Mapping 传感器缩回失败" },
            {"409","Mapping 传感器位置数据不正确" },
            {"411","Mapping 传感器高度不一致" },
            {"412","工位 VIA 参数未使能" },
            {"413","不是有效的 Mapping 工位" },
            {"414","手指有晶圆无法 mapping" },
            {"415","采集的数据个数错误" },
            {"416","采集的晶圆厚度过小" },
            {"417","晶圆位置超出有效范围" },
            {"418","晶圆上下沿槽数错误" },
            {"419","斜片上下沿槽数错误" },
            {"550","工位号超范围" },
            {"552","VIA 参数错误" },
            {"553","MAPVIA 参数错误" },
            {"600","系统未上电" },
            {"602","指令正在执行中" },
            {"603","系统上电失败" },
            {"604","示教器控制中" },
            {"605","机械手运动中停止" },
            {"609","系统存在错误" },
            {"610","示教盒急停启动" },
            {"611","驱动器报警" },
            {"629","驱动器存在报警" },
            {"705","LOAD 状态未知" },
            {"712","真空吸附动作失败" },
            {"730","PLACE 前 LOAD 状态错误" },
            {"731","PLACE 后 LOAD 状态错误" },
            {"734","PLACE 执行 Extend 过程中未检测到晶圆" },
            {"736","PLACE 执行 Retract 过程中检测到晶圆" },
            {"740","PICK 前 LOAD 状态错误" },
            {"741","PICK 后 LOAD 状态错误" },
            {"744","PICK 执行 Extend 过程中检测到晶圆" },
            {"745","PICK 执行 Retract 过程中未检测到晶圆" },
            {"1006","非法的 IO 端口号" },
            {"1314","PITCH 轴超界" },
            {"1315","关节位置超界" },
            {"1316","关节位置超硬限" },
            {"1320","机械手跟踪差超限错误" },
            {"1321","机械手发生碰撞" },
            {"1322","机械手超出工作区" },
            {"1323","关节速度超限" },
            {"1401","当前位置不正确" },
            {"1407","大气压力不足" },
            {"1412","晶圆已滑出" },
            {"1500","打开门失败" },
            {"1501","关闭门失败" },
            {"1502","门开关状态不对" },
            {"1503","门松开失败" },
            {"1504","门夹紧失败" },
            {"1506","当前不是自动门模式" },
            {"1507","开盖检测互锁" },
            {"1508","开门不允许运动" },
            {"1509","无 casette 盒不允许运动" },
            {"1510","安全检测触发" },
            {"1511","R 轴未运动到位" },
            {"1512","门动作开关未使能" },
            {"1513","运动开关未使能" },
        };
        //
        #endregion
        #region 暴露变量
        public override bool IsConnected => _serialport.IsOpen();
        public override RState Status => _status;
        public override bool IsReady => _status == RState.Init || _status == RState.End;
        public override bool IsError => _status == RState.Failed || _status == RState.Timeout;
        public override bool IsInit => _status == RState.Init;
        public override bool IsDashWaferError => _IsDashWaferError;
        private string[] _slotMap = new string[25];
        public string SlotMap
        {
            get
            {
                WaferInfo[] wafers = WaferManager.Instance.GetWafers(ModuleHelper.Converter(Name));
                string slot = "";
                for (int i = 0; i < 25; i++)
                {
                    slot += wafers[i].IsEmpty ? "0" : "1";
                }
                return slot;
            }
        }
        private bool _OutDoorIsOpen
        {
            get
            {
                switch (_moduleName)
                {
                    case ModuleName.VCE1:
                        //2024-05-20 16:35:34 泓浒四边形硬件还未实现
                        //DEVICE.GetDevice("SETM").VCEACassPresent
                        return _vcedoorflag;
                    case ModuleName.VCEA:
                        if (DEVICE.GetDevice("TM").VCEACassPresent)
                        {
                            _LPMs[0].HasCassette = true;
                        }
                        else
                        {
                            _LPMs[0].HasCassette = false;
                            WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
                        }
                        return !DEVICE.GetDevice("TM").VCEALOCKED;
                    case ModuleName.VCEB:
                        if (DEVICE.GetDevice("TM").VCEBCassPresent)
                        {
                            _LPMs[0].HasCassette = true;
                        }
                        else
                        {
                            _LPMs[0].HasCassette = false;
                            WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
                        }
                        return !DEVICE.GetDevice("TM").VCEBLOCKED;
                    default:
                        return false;
                }
            }
        }
        public override bool OutDoorIsOpen => _OutDoorIsOpen;
        private bool _vcedoorflag;
        private bool _hasProtrusion
        {
            get
            {
                switch (_moduleName)
                {
                    case ModuleName.VCE1:
                        //2024-05-20 16:35:34 泓浒四边形硬件还未实现
                        //DEVICE.GetDevice("SETM").VCEProtrusion
                        return true;
                    case ModuleName.VCEA:
                        if (DEVICE.GetDevice("TM").VCEAProtrusion)
                        {
                            _LPMs[0].Protrusion = true;
                            return true;
                        }
                        else
                        {
                            _LPMs[0].Protrusion = false;
                            return false;
                        }
                    case ModuleName.VCEB:
                        if (DEVICE.GetDevice("TM").VCEBProtrusion)
                        {
                            _LPMs[0].Protrusion = true;
                            return true;
                        }
                        else
                        {
                            _LPMs[0].Protrusion = false;
                            return false;
                        }
                    default:
                        return false;
                }
            }
        }
        #endregion
        public SunWayVce(int slot, ModuleName moduleName) : base(slot, moduleName)
        {
            _moduleName = moduleName;
            _vcedoorflag = false;
            _IsAsciiMode = true;
            _portname = SC.GetStringValue($"{moduleName}.Port");
            _serialport = new AsyncSerialPort(_portname, 9600, 8, Parity.None, StopBits.One, _newline, _IsAsciiMode);
            _serialport.Open();
            _status = RState.Init;
            _serialport.OnDataChanged += onDataChange;
            _thread = new PeriodicJob(50, fnTimer, _moduleName.ToString(), true);
            if (moduleName == ModuleName.VCE1)
                _LPMs[0] = new Loadport(ModuleName.LP1);
            else
                _LPMs[0] = new Loadport((moduleName - ModuleName.VCEA) + ModuleName.LP1);
            CarrierManager.Instance.DeleteCarrier(_LPMs[0].Module.ToString());
            WaferManager.Instance.DeleteWafer(_LPMs[0].Module, 0, 25);
            CarrierManager.Instance.SubscribeLocation(_LPMs[0].Module.ToString(), 1);
            Action _subscribeLoc = (ModuleName module, int waferCount) => {
                if (ModuleHelper.IsInstalled(module))
                {
                    WaferManager.Instance.SubscribeLocation(module, waferCount);
                }
            };
            _subscribeLoc(_LPMs[0].Module, slot);
        }
        private bool fnTimer()
        {
            lock (_locker)
            {
                //采用ascii传输
                if (_IsAsciiMode)
                {
                    //有数据尚未处理
                    while (_lstAsciiMsgs.Count > 0)
                    {
                        string _needHandle = _lstAsciiMsgs.First.Value;
                        HandleSingleMsg(_needHandle);
                        _lstAsciiMsgs.RemoveFirst();
                    }
                }
                //采用binary
                else
                {
                }
            }
            return true;
        }
        private void HandleSingleMsg(string rawmsgs)
        {
            string[] msgs = rawmsgs.Split('\r');
            foreach (var Msg in msgs)
            {
                string msg = Msg.Trim();
                LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"{_moduleName} Receive msg=>{msg}");
                if (!string.IsNullOrEmpty(msg))
                {
                    //action set petrify _BKGRDY结束
                    switch (_currentVceMessage.Head)
                    {
                        case VceMessageHead.Action:
                        case VceMessageHead.Set:
                        case VceMessageHead.Petrify:
                            switch (msg)
                            {
                                //设备收到 开始运行 目前状态在下发
                                case "_RDY":
                                    LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"vce {_currentVceMessage.Head} over");
                                    switch (_currentVceMessage.Command)
                                    {
                                        case VceCommand.Home:
                                        case VceCommand.Map:
                                        case VceCommand.GotoLP:
                                            _currentSlot = 0;
                                            break;
                                        case VceCommand.DoorClose:
                                            _vcedoorflag = false;
                                            break;
                                        case VceCommand.DoorOpen:
                                            _vcedoorflag = true;
                                            break;
                                    }
                                    _status = RState.End;
                                    break;
                                //异常处理
                                default:
                                    _status = RState.Failed;
                                    string reason;
                                    Errorhandle(msg, out reason);
                                    LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, reason);
                                    break;
                            }
                            break;
                        case VceMessageHead.Read:
                            //如果收到的信息符合
                            if (_match_ReadMsg.IsMatch(msg))
                            {
                                //收到消息 用于结束
                                _HasReceiveMsg = true;
                                switch (_currentVceMessage.Command)
                                {
                                    //处理wafer 信息为map数据
                                    case VceCommand.ReadMap:
                                        ReadMapData(msg);
                                        break;
                                    case VceCommand.CheckStatus:
                                        ReadStatus(msg);
                                        break;
                                }
                            }
                            //_RDY查询结束
                            else
                            {
                                if (msg == "_RDY")
                                {
                                    if (_HasReceiveMsg)
                                    {
                                        _status = RState.End;
                                    }
                                    else
                                    {
                                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is over but not receive msg! raw message:{_currentMsg}");
                                        _status = RState.Failed;
                                    }
                                }
                                else
                                {
                                    _status = RState.Failed;
                                    LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Read Message is invalid: receive message {msg} and send message {_currentMsg}");
                                }
                            }
                            break;
                    }
                }
            }
        }
        private void ReadStatus(string msg)
        {
            try
            {
                //BRa,SLbb,CPc,WPd,ERe
                string[] status = msg.Split(',');
                _currentSlot = Convert.ToInt32(status[4].Substring(2, 2));
            }
            catch (Exception ex)
            {
                LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"illegal msg:{msg}, {ex.Message}");
            }
        }
        private void ReadMapData(string msg)
        {
            //string waferinfo = "";
            string[] waferitems = msg.Split(',');
            //智能模式 可以识别叠片
            for (int i = 2; i <= waferitems.Length - 1; ++i)
            {
                switch (waferitems[i])
                {
                    case "O":
                        WaferManager.Instance.DeleteWafer(_LPMs[0].Module, i - 2);
                        break;
                    case "X":
                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Normal);
                        break;
                    case "I":
                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Thin wafer.");
                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Dummy);
                        break;
                    case "T":
                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Thick or Double wafer.");
                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
                        break;
                    case "C":
                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Crossed wafer.");
                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
                        break;
                    case "?":
                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1}:Unknown error wafer.");
                        WaferManager.Instance.CreateWafer(_LPMs[0].Module, i - 2, WaferStatus.Double);
                        break;
                    default:
                        LOG.Write(eEvent.ERR_VCE_COMMON_Failed, _moduleName, $"Slot {i - 1} Receive Error Msg:{waferitems}");
                        break;
                }
            }
            _LPMs[0].IsMapped = true;
        }
        private void Errorhandle(string msg, out string reason)
        {
            if (_matchErrorCode.IsMatch(msg))
            {
                //若是匹配
                //包含原因
                string errorcode = _matchErrorCode.Match(msg).Value;
                if (_ErrorCode2Reason.ContainsKey(errorcode))
                {
                    if (errorcode == "L13")
                        _IsDashWaferError = true;
                    reason = _ErrorCode2Reason[errorcode];
                }
                else
                {
                    reason = "未找到相关Error Code";
                }
            }
            else
            {
                //若不匹配
                reason = "回复消息不符合标准格式";
            }
        }
        private void onDataChange(string oneLineMessage)
        {
            lock (_locker)
            {
                if (string.IsNullOrEmpty(_newline))//没有CR
                {
                    _lstAsciiMsgs.AddLast(oneLineMessage);//将消息添加到最后
                    return;
                }
                string[] array = oneLineMessage.Split(_newline.ToCharArray());//按照cr分开通讯数据
                foreach (string text in array)
                {
                    if (!string.IsNullOrEmpty(text))
                    {
                        _lstAsciiMsgs.AddLast(text + _newline);//存进list中等待处理
                    }
                }
            }
        }
        public override bool ServerUp()
        {
            //if (!CheckVceStatus())
            //    return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Set, Command = VceCommand.ServerUp, Param = "ALL,ON" };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool HomeALL()
        {
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home, Param = "ALL" };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Home(string axis)
        {
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Home, Param = axis };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool CheckStatus()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Read, Command = VceCommand.CheckStatus };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool CloseDoor()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorClose };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        /// 
        /// 开门提示
        /// 在honghuVCE中没有ATM信号的内部卡控 可能会导致开门的压差
        /// 因此每一次都要增加判断,只要引用此处功能的,前面都需要有判断
        /// 
        /// 
        /// 
        public override bool OpenDoor()
        {
            //如果其他指令正在执行 且  
            //if (!CheckVceStatus())
            //    return false;
            if (_IsDashWaferError)
                _IsDashWaferError = false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.DoorOpen };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Load()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Load };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool UnLoad()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.UnLoad };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Map()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Map };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool ReadMap()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Read, Command = VceCommand.ReadMap, Param = "S" };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            _HasReceiveMsg = false;
            return _serialport.Write(_currentMsg);
        }
        public override bool Goto(int Targetslot)
        {
            if (!CheckVceStatus())
                return false;
            LOG.Write(eEvent.EV_VCE_COMMON_INFO, _moduleName, $"SlotNum:{Targetslot}");
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.Goto, Param = (Targetslot + 1).ToString().PadLeft(2, '0') };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool GotoLP()
        {
            if (!CheckVceStatus())
                return false;
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Action, Command = VceCommand.GotoLP };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool ClearError()
        {
            _currentVceMessage = new VceMessage { Head = VceMessageHead.Set, Command = VceCommand.ClearError };
            _currentMsg = _currentVceMessage.toSunWayString() + _newline;
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
    }
}