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.RT.ModuleLibrary.VceModules;
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;
namespace Venus_RT.Devices.VCE
{
    //定义Vce动作
    public enum VceCommand
    {
        Home,
        DoorClose,
        DoorOpen,
        Goto,
        Load,
        UnLoad,
        Map,
        ReadMap,
    }
    public enum VceMessageHead
    {
        Action,
        Read,
        Set,
        Petrify
    }
    /// 
    /// 泓浒Vce驱动 下发指令等
    /// 
    public class HongHuVce : VceModuleBase
    {
        #region 私有变量
        private AsyncSerialPort _serialport;
        private string _portname;
        private string _newline = "\n\r";//终止符 0A 0D
        private object _locker = new object();
        private bool _IsAsciiMode;
        private LinkedList _lstAsciiMsgs = new LinkedList();
        private PeriodicJob _thread;
        private Regex _matchErrorCode = new Regex(@"(?<=_BKGERR )(.*)");
        private ModuleName _moduleName;
        private RState _status;
        private string _currentMsg;
        //后期补充
        private Dictionary _ErrorCode2Reason = new Dictionary()
        {
            {"A6","设备动作,但是发生异常" },
            {"A8","设备检查互锁,发现无法执行" },
        };
        //
        private Dictionary _Command2Msg = new Dictionary()
        {
            //Action
            {VceCommand.Home,    "HM"    },
            {VceCommand.Load,    "LOAD"  },
            {VceCommand.UnLoad,  "UNLOAD"},
            {VceCommand.Map,     "MP"    },
            {VceCommand.Goto,    "GC"    },
            //Read
            {VceCommand.ReadMap,  "MI" },
            //Set
            
        };
        private Dictionary _Type2Head = new Dictionary()
        {
            {VceMessageHead.Action,  "A"},
            {VceMessageHead.Read,    "R"},
            {VceMessageHead.Set,     "S"},
            {VceMessageHead.Petrify, "P"},
        };
        #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;
        #endregion
        //传入slot数量
        public HongHuVce(int slot, ModuleName moduleName) : base(slot, moduleName)
        {
            _moduleName = moduleName;
            _IsAsciiMode = true;
            _portname = SC.GetStringValue("VCE.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, "VCE", true);
        }
        /// 
        /// 对处理过的数据list进行处理
        /// 将每条数据进行解析
        /// 
        /// 
        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;
        }
        /// 
        /// 处理单条信息的函数
        /// 1、判断结束 2、判断错误
        /// 
        /// 需要处理的单条回复
        private void HandleSingleMsg(string msg)
        {
            //
            if (!string.IsNullOrEmpty(msg))
            {
                //动作
                if (_currentMsg.Contains(",A,"))
                {
                    switch (msg)
                    {
                        //设备收到 开始运行 目前状态在下发
                        case "_RDY":
                            break;
                        //设备执行完毕
                        case "_BKGRDY":
                            _status = RState.End;
                            break;
                        //异常处理
                        default:
                            _status = RState.Failed;
                            string reason = string.Empty;
                            if (_matchErrorCode.IsMatch(msg))
                            {
                                //若是匹配
                                //包含原因
                                string errorcode = _matchErrorCode.Match(msg).Value;
                                if (_ErrorCode2Reason.ContainsKey(errorcode))
                                {
                                    reason = _ErrorCode2Reason[errorcode];
                                }
                                else
                                {
                                    reason = "未找到相关Error Code";
                                }
                            }
                            else
                            {
                                //若不匹配
                                reason = "回复消息不符合标准格式";
                            }
                            LOG.Write(eEvent.ERR_DEVICE_INFO, _moduleName, reason);
                            break;
                    }
                }
                //读取
                if (_currentMsg.Contains(",R,") && msg.Contains(",X,"))
                {
                    string readtype = msg.Split(',')[2];
                    switch (readtype)
                    {
                        //处理wafer 信息为map数据
                        case "MI":
                            string waferinfo = "";
                            string[] waferitems = msg.Split(',');
                            for (int i = 3; i < waferitems.Length - 1; i++)
                            {
                                //从16进制字符转义回二进制
                                string wafersingleinfo = Convert.ToString(Convert.ToInt32(waferitems[i], 16), 2);
                                if (wafersingleinfo.Length < 4)
                                    wafersingleinfo = '0' * (4 - wafersingleinfo.Length) + wafersingleinfo;//补位
                                waferinfo = wafersingleinfo + waferinfo;//添加到数据中
                            }
                            //请将数据按照反向槽位进行解析存入到wafermanager中
                            break;
                    }
                }
            }
        }
        /// 
        /// 处理新到的数据
        /// 利用linkedlist处理拆包 粘包情况
        /// 
        /// 新到数据
        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 string Option2Message(VceMessageHead msgtype, VceCommand name, string param = "")
        {
            if (string.IsNullOrEmpty(param))//含尾参
                return $"00,{_Type2Head[msgtype]},{_Command2Msg[name]}{_newline}";
            else//不含尾参 目前只允许一个
                return $"00,{_Type2Head[msgtype]},{_Command2Msg[name]},{param},{_newline}";
        }
        public override bool CloseDoor()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.DoorClose);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool HomeALL()
        {
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Home, "ALL");
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Home(string axis)
        {
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Home, axis);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool OpenDoor()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.DoorOpen);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Load()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Load);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool UnLoad()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.UnLoad);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Map()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Map);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool ReadMap()
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Read, VceCommand.ReadMap);
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
        public override bool Goto(int Targetslot)
        {
            if (!CheckVceStatus())
                return false;
            _currentMsg = Option2Message(VceMessageHead.Action, VceCommand.Goto, Targetslot.ToString());
            _status = RState.Running;
            return _serialport.Write(_currentMsg);
        }
    }
}