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 MECF.Framework.RT.EquipmentLibrary.HardwareUnits.Robot;
using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using Venus_Core;

namespace Venus_RT.Devices.PreAligner
{
    public class SunWayVPA : IPreAlign
    {
        private AsyncSerialPort _serialport;//串口
        private string _newLine = "\r\n";//结束符号
        private object _locker = new object();//锁变量
        private bool _IsAsciiMode = true;
        private PeriodicJob _thread;
        private RState _state;
        private Regex _catchErrorCode = new Regex(@"(?<=_ERR )(.*)");
        private Regex _checkData = new Regex(@"(?<=DATA)(.*)");
        private LinkedList<string> _lstMessage = new LinkedList<string>();
        private ModuleName _module;

        private enum AlignerAction
        {
            Home,
            Align,
            AlignWithAngle,
            Reset,
            Scan,
            RsLT,
            ServeUp
        }
        private Dictionary<int, string> _ErrorCode2Msg = new Dictionary<int, string>()
        {
            { 16 , "" },
        };
        private Dictionary<AlignerAction, string> _Command2Msg = new Dictionary<AlignerAction, string>()
        {
            //Action
            { AlignerAction.Align         , "ALIGNER ALGN" },//旋转到预设的站点方向
            { AlignerAction.AlignWithAngle, "MOVT REL" },//旋转到指定的角度
            { AlignerAction.Home          , "ALIGNER HOME" },//Home 初始化时 error时用
            { AlignerAction.Reset         , "RSET" },//重置 error时用
            { AlignerAction.Scan          , "ALIGNER SCAN" },//扫描整个Wafer参数
            { AlignerAction.RsLT          , "ALIGNER RSLT" },
            { AlignerAction.ServeUp       , "SET SERVOS ON"}
            //Read
            //{ "" , "RQCD" },
            //{ "" , "RQCCDPOS" },
            //{ "" , "RQID" },
            //{ "" , "RQPS" },
            //Set
            //{ "" , "" },
            //Welding
            //{ "" , "SVCD" },
        };
        public ModuleName Module => _module;
        public bool IsConnect => _serialport.IsConnected;
        public RState Status => _state;//状态

        public bool IsError => _state == RState.Failed || _state == RState.Timeout;

        private int _ROffset = 0;
        private int _TOffset = 0;
        private bool _IsOverRange = false;
        public int ROffset => _ROffset;

        public int TOffset => _TOffset;

        public bool IsOverRange => _IsOverRange;

        public SunWayVPA(ModuleName module)
        {
            _module = module;
            string port = SC.GetStringValue($"{module}.AlignerPort");
            _serialport = new AsyncSerialPort(port, 9600, 8, Parity.None, StopBits.One, _newLine, _IsAsciiMode);
            _serialport.Open();
            WaferManager.Instance.SubscribeLocation(ModuleName.Aligner1, 1);
            _serialport.OnDataChanged += OnReceiveData;
            _state = RState.Init;
            _thread = new PeriodicJob(50, OnTimer, "OnTimer->Aligner1");
            _thread.Start();
        }

        private void OnReceiveData(string obj)
        {
            lock (_locker)
            {
                if (string.IsNullOrEmpty(_newLine))//没有CR
                {
                    _lstMessage.AddLast(obj);//将消息添加到最后
                    return;
                }
                string[] array = obj.Split(_newLine.ToCharArray());//按照cr分开通讯数据
                foreach (string text in array)
                {
                    if (!string.IsNullOrEmpty(text))
                    {
                        _lstMessage.AddLast(text + _newLine);//存进list中等待处理
                    }
                }
            }
        }

        //定时器处理新信息为状态
        private bool OnTimer()
        {
            //线程锁
            lock (_locker)
            {
                //采用ascii码模式处理
                if (_IsAsciiMode)
                {
                    //存在尚未处理的信息
                    while (_lstMessage.Count > 0)
                    {
                        //获取头上的数据
                        string handlemsg = _lstMessage.First.Value;
                        Handlemessage(handlemsg);
                        _lstMessage.RemoveFirst();
                    }
                }
                //采用binary模式处理
                else
                {

                }

            }
            return true;
        }

        private void Handlemessage(string handlemsg)
        {
            //需要按类型进行处理 Action需要将其error
            bool IsAction = true;
            handlemsg = handlemsg.Trim();
            if (IsAction)
            {
                switch (handlemsg)
                {
                    //正确执行
                    case "_RDY":
                        _state = RState.End;
                        break;
                    //返回
                    default:
                        if (_checkData.IsMatch(handlemsg))
                        {
                            string[] data = handlemsg.Split(' ');
                            _ROffset = Convert.ToInt32(data[2]);
                            _TOffset = Convert.ToInt32(data[3]);

                            if (data[5] == "Y")
                            {
                                _IsOverRange = true;
                                LOG.Write(eEvent.WARN_DEVICE_INFO, Module, $"Wafer offset is over range");
                            }

                            if (data[5] == "N")
                            {
                                _IsOverRange = false;
                                LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Wafer offset is in range");
                            }

                            LOG.Write(eEvent.EV_DEVICE_INFO, Module, $"Ro{_ROffset} To{_TOffset}");
                        }
                        else
                        {
                            _state = RState.Failed;
                            //分两种 1、不按格式的未知错误 2、有错误码的
                            if (_catchErrorCode.IsMatch(handlemsg))
                            {
                                int errorcode = Convert.ToInt32(_catchErrorCode.Match(handlemsg).Value);
                                if (_ErrorCode2Msg.ContainsKey(errorcode))
                                {
                                    LOG.Write(eEvent.ERR_DEVICE_INFO, Module, _ErrorCode2Msg[errorcode]);
                                }
                                else
                                {
                                    LOG.Write(eEvent.ERR_DEVICE_INFO, Module, $"未知错误码{errorcode}");
                                }
                            }
                            else
                            {
                                LOG.Write(eEvent.ERR_DEVICE_INFO, Module, "未收录相关错误");
                            }
                        }
                        break;
                }
            }

        }

        private bool SendMessage(string msg, params string[] args)
        {
            _state = RState.Running;
            if (args.Length > 0)//含参
            {
                foreach (string arg in args)
                    msg = msg + " " + arg;
                LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to SunWay Aligner: {msg}");
                return _serialport.Write(msg + _newLine);
            }
            else//空参
            {
                LOG.WriteSingeLine(eEvent.EV_DEVICE_INFO, _module, $"Send Command to SunWay Aligner: {msg}");
                return _serialport.Write(msg + _newLine);
            }
        }

        public bool Align()
        {
            if (!CanSendCommand())
                return false;
            return SendMessage(_Command2Msg[AlignerAction.Align]);
        }

        public bool AlignWithAngle(float angle)
        {
            if (!CanSendCommand())
                return false;
            int ang = (int)Math.Floor(angle);//不能用Convert.toInt32("angle") 其遵守四舍五入 此处需向上取整
            return SendMessage(_Command2Msg[AlignerAction.AlignWithAngle], ang.ToString());
        }

        public bool Home()
        {
            return SendMessage(_Command2Msg[AlignerAction.Home]);
        }

        public bool QueryOffset()
        {
            if (!CanSendCommand())
                return false;
            return SendMessage(_Command2Msg[AlignerAction.RsLT]);
        }

        public bool ReSet()
        {
            if (!IsError)
                return false;
            return SendMessage(_Command2Msg[AlignerAction.Reset]);
        }

        public bool SCAN()
        {
            if (!CanSendCommand())
                return false;
            return SendMessage(_Command2Msg[AlignerAction.Scan]);
        }

        public bool ServeUp()
        {
            return SendMessage(_Command2Msg[AlignerAction.ServeUp]);
        }

        public bool CanSendCommand()
        {
            if (Status == RState.Init)
            {
                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is not homed, please home first.");
                return false;
            }
            else if (Status == RState.Running)
            {
                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner is busy, please wait a minute");
                return false;
            }
            else if (Status == RState.Failed || Status == RState.Timeout)
            {
                LOG.Write(eEvent.ERR_DEVICE_INFO, _module, "Aligner has a error, please check and fix the hardware issue and home it");
                return false;
            }

            return true;
        }
    }
}