using Aitex.Core.RT.Event;
using Aitex.Core.RT.Log;
using Aitex.Core.Util;
using MECF.Framework.Common.Equipment;
using CyberX8_Core;
using CyberX8_RT.Devices.YASKAWA;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Contexts;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;

namespace CyberX8_RT.Devices.EFEM
{
    public class JetMessageHandler : Singleton<JetMessageHandler>, IEfemMessageHander
    {
        private const string ERROR_MSG = "hardware message invalid";

        public EfemMessage ToMessage(string context)
        {
            if (string.IsNullOrEmpty(context) || context.Length < 3)
                throw new ArgumentNullException(ERROR_MSG);

            EfemMessage msg = new EfemMessage { RawString = context, Direct = MsgDirection.From, Data = new List<string>() };

            // remove EOT
            string messageBody = context.Substring(0, context.IndexOf(EfemMessage.EOF) + 1);

            try
            {
                // split up the string
                string[] sBodies = messageBody.Split(Constant.delimiters);

                string sHead = sBodies[0];
                string sBasic = sBodies[1];
                string sPort = sBodies[2];

                // Head
                if (Enum.TryParse(sHead, true, out EfemMessage.MsgHead msgHead))
                {
                    msg.Head = msgHead;
                }

                switch (msg.Head)
                {
                    case EfemMessage.MsgHead.ACK:
                    case EfemMessage.MsgHead.MOV:
                    case EfemMessage.MsgHead.INF:
                    case EfemMessage.MsgHead.EVT:
                        // Basic
                        msg.Operation = EfemConstant.ToOperation(sBasic);

                        // Port
                        if (Regex.IsMatch(sPort, @"P[123]$"))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else
                        {
                            msg.Module = ModuleName.EFEM;
                        }

                        // Data
                        switch (msg.Operation)
                        {
                            case EfemOperation.StateTrack:
                            case EfemOperation.GetWaferInfo:
                                msg.Data.Add(sBodies[3]);
                                break;
                            case EfemOperation.CarrierId:
                                msg.Data.Add(msg.RawString.Substring("INF:CSTID/P1/".Length));
                                break;
                            case EfemOperation.SigStatus:
                                msg.Data.Add(sBodies[2]);
                                msg.Data.Add(sBodies[3]);
                                msg.Data.Add(sBodies[4]);
                                break;
                            case EfemOperation.Ready:
                                msg.Data.Add(sBodies[2]);
                                break;
                            default:
                                break;
                        }
                        break;

                    case EfemMessage.MsgHead.NAK:
                        msg.Operation = EfemConstant.ToOperation(sBasic);
                        // Port
                        if (Regex.IsMatch(sPort, @"P[123]$"))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else
                        {
                            msg.Module = ModuleName.EFEM;
                        }

                        msg.Factor = sBodies[1];
                        msg.Data.Add(sBodies[2]);

                        msg.Operation = EfemConstant.ToOperation(sBasic);
                        break;

                    case EfemMessage.MsgHead.CAN:
                        msg.Operation = EfemConstant.ToOperation(sBasic);
                        // Port
                        if (Regex.IsMatch(sPort, @"P[123]$"))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else
                        {
                            msg.Module = ModuleName.EFEM;
                        }
                        // CAN:ERROR/CLEAR;
                        int a1 = messageBody.IndexOf(':');
                        int a3 = messageBody.IndexOf(';');

                        int a2 = messageBody.IndexOf('|');
                        if (a2 > 0)
                        {
                            msg.Data.Add(messageBody.Substring(a1 + 1, a2 - a1 - 1));
                            msg.Factor = messageBody.Substring(a2 + 1, a3 - a2 - 1);
                        }
                        else
                        {
                            int a8 = messageBody.IndexOf('/');
                            msg.Factor = sBodies[2];
                        }
                        break;

                    case EfemMessage.MsgHead.ABS:
                        msg.Operation = EfemConstant.ToOperation(sBasic);
                        // Port
                        if (Regex.IsMatch(sPort, @"P[123]$"))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else if (Regex.IsMatch(sPort, @"ALIGN\d?", RegexOptions.IgnoreCase))
                        {
                            msg.Module = sPort.ToModule();
                        }
                        else
                        {
                            msg.Module = ModuleName.EFEM;
                        }
                        // ABS:INIT/ALL|ERROR/SYSTEM_FF10/UNDEFINITION;
                        int a4 = messageBody.IndexOf('|');
                        int a5 = messageBody.IndexOf(';');

                        // ABS:LOAD/LLLB01/ARM2|ERROR/RB|2B80;


                        string errStr = messageBody.Substring(a4 + 1, a5 - a4 - 1);
                        //分割位置和因素 最后一位是需要处理
                        string[] a6 = errStr.Split('/', '|');

                        if (a6.Length < 3)
                        {
                            //因为小于导致后续使用相关变量时会越界
                            //需要补全 已保证使用
                            msg.Factor = errStr;
                            msg.Data.Add($"ABS 格式错误");
                            msg.Data.Add($"{errStr}");
                            LOG.Write(eEvent.WARN_EFEM_COMMON_WARN, ModuleName.EFEM, $"ABS 格式错误 {errStr}");
                        }
                        else
                        {
                            msg.Factor = a6[0];
                            msg.Data.Add(a6[1]);
                            string errorcode = a6[2].Substring(1);
                            if (Constant._EFEMHWErrorCode2Msg.ContainsKey(errorcode))
                                msg.Data.Add(Constant._EFEMHWErrorCode2Msg[errorcode]);
                            else if (!string.IsNullOrEmpty(MatchError(errorcode)))
                                msg.Data.Add(MatchError(errorcode));
                            else
                                msg.Data.Add(a6[2]);
                        }
                        break;
                }
            }
            catch (Exception ex)
            {
                EV.PostAlarmLog(ModuleName.EFEM.ToString(), $"收到[{context}],解析出错[{ex.Message}]");
            }

            return msg;
        }

        private string MatchError(string errorcode)
        {
            foreach (KeyValuePair<Regex, string> item in Constant._EFEMHWRegexError2Msg)
            {
                if (item.Key.IsMatch(errorcode))
                    return item.Value;
            }
            return string.Empty;
        }

    }
}