using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Windows.Forms;
using System.Xml;
using DDUtilityApp.DATA;
using DDUtilityApp.LOGPARSER.DATA;
using DDUtilityApp.SECS;
using JWH;
using JWH.CONTROL;
using Telerik.WinControls.UI;

namespace DDUtilityApp.LOGPARSER.PARSER
{

    public class EisParser0 : LogParser
    {

        #region [ Properties ] ------------------------------------------------

        #endregion

        #region [ EisParser ] -------------------------------------------------

        public EisParser0() : base()
        {
            this.Text = $"[EverOne] EIS Log Viewer";
            this.LogDTimeStart = 6;
            this.LogDTime = "MM-dd HH:mm:ss.fff";
        }

        public EisParser0(params string[] files) : base(files)
        {
        }

        #endregion

        #region [ Method ] ----------------------------------------------------

        public override bool Parsing()
        {
            try
            {
                base.Initilize();
                foreach (string file in this.Files)
                {
                    StreamReader reader = null;
                    try
                    {
                        reader = new StreamReader(file, Encoding.Default);

                        long readerPosition = reader.BaseStream.Position;
                        string strLine = this.GetReadLine(reader);
                        while (strLine != null)
                        {
                            Parser parser = this.GetParser(strLine);
                            if (parser == null)
                            {
                                strLine = this.GetReadLine(reader);
                                continue;
                            }

                            StandardData standardData = parser(reader, ref strLine) as StandardData;
                            if (standardData != null)
                            {
                                standardData.Column5 = System.IO.Path.GetFileName(file);
                                //if (standardData.Body != null) standardData.Body.Clear();
                            }
                        }
                    }
                    catch (Exception ex01)
                    {
                        XLogger.Instance.Fatal(ex01);
                    }

                    if (reader != null) reader.Close();
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return false;
            }
            finally
            {
                this.SendStandardData.Clear();
            }

            return true;
        }

        protected Parser GetParser(string strLine)
        {
            Parser parser = null;
            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return parser;
                if (strLine.Length < this.LogDTime.Length) return parser;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return parser;
                for (int i = 0; i < strValues.Length; i++) strValues[i] = strValues[i].ToUpper();

                if (strValues.Length > 3 && strValues[4].Trim() == "TIBCO") return this.TIBCO_Parser;
                if (strLine.ToUpper().Contains("EXCEPTION")) return this.EXCEPTION_Parser;

                if (strValues[2].Trim().StartsWith("EQP"))
                {
                    if (new string[] { "DATA", }.Contains(strValues[3])) parser = this.SECS_Parser;
                    else if (new string[] { "TIMEOUT" }.Contains(strValues[4])) parser = this.SECS_Parser;
                    else if (new string[] { "ERROR" }.Contains(strValues[1])) parser = this.ERROR0_Parser;
                    else if (new string[] { "ERROR" }.Contains(strValues[3])) parser = this.ERROR1_Parser;
                    else parser = this.PLC_Parser;
                }
                else if (strValues[2].Trim() == "RMS")
                {
                    parser = this.RMS_Parser;
                }
                else if (strValues[2].Trim() == "FDC")
                {
                    parser = this.FDC_Parser;
                }
                else if (strValues[2].Trim() == "RTD")
                {
                    parser = this.RTD_Parser;
                }
                else if (strValues[2].Trim() == "MES")
                {
                    parser = this.MES_Parser;
                }
                else if (strValues[2].Trim() == "ADD" || strValues[1].Trim() == "DISPOSE")
                {
                    parser = this.TID_Parser;
                }
                else if (strValues[2].Trim() == "▶▶" || strValues[3].Trim() == "▶▶")
                {
                    // INFO  05-03 13:44:18.073 ▶▶ AreYouThereRequest Time Over 발생 : FDC ◀◀
                    // INFO  05-03 13:44:18.080 INFO: ▶▶ AreYouThereRequest Time Over 발생 : FDC ◀◀
                    parser = this.ERROR2_Parser;
                }
                else if (strValues[2].Trim().ToUpper().IndexOf("EXCEPTION") >= 0)
                {
                    parser = this.EXCEPTION_Parser;
                }
                else
                {
                    if (new string[] { strValues[2], strValues[3] }.Contains("TRANSACTIONID")) parser = this.TRANSACTIONID_Parser;
                    else if (new string[] { strValues[2], strValues[3] }.Contains("TID")) parser = this.TRANSACTIONID_Parser;
                    else parser = this.ETC_Parser;
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return parser;
            }

            return parser;
        }

        private string[] GetHeaderValues(string strLine, params string[] spliter)
        {
            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return null;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return null;

                DateTime dtime = DateTime.MinValue;
                string strDTime = strLine.Substring(this.LogDTimeStart, this.LogDTime.Length);
                if (DateTime.TryParseExact(strDTime, this.LogDTime, null, System.Globalization.DateTimeStyles.None, out dtime) == false) return null;

                if (spliter.Length == 0) { spliter = new string[] { ":", "|", " " }; };
                List<string> lstValues = new List<string>();
                lstValues.Add(dtime.ToString("yyyy-MM-dd HH:mm:ss.fff"));
                lstValues.Add(strLine.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries).First());
                lstValues.AddRange(strLine.Substring(this.LogDTimeStart + this.LogDTime.Length).Split(spliter, StringSplitOptions.RemoveEmptyEntries));

                return lstValues.ToArray();
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                return null;
            }
        }

        private bool IsEnd(string strLine)
        {
            try
            {
                string strDTime = string.Empty;
                DateTime dtime = DateTime.Now;
                if (strLine.Length > this.LogDTimeStart + this.LogDTime.Length)
                {
                    strDTime = strLine.Substring(this.LogDTimeStart, this.LogDTime.Length);
                    return DateTime.TryParseExact(strDTime, this.LogDTime, null, System.Globalization.DateTimeStyles.None, out dtime);
                }
            }
            catch (Exception ex)
            {
                //XLogger.Instance.Fatal(ex);
            }

            return false;
        }

        private SECSItem GetSECSItem(string message, string text)
        {
            if (string.IsNullOrEmpty(message)) return null;
            if (string.IsNullOrEmpty(text)) return null;
            SECSItem root = null;

            try
            {
                MemoryStream stream = new MemoryStream(text.ConvertBytes());
                StreamReader reader = new StreamReader(stream);

                SECSItem parent = null;
                SECSItem item = null;
                char chValue;
                string strValue = string.Empty;
                while (!reader.EndOfStream)
                {
                    chValue = (char)reader.Read();

                    if (new char[] { ' ', '>', (char)0x0D, (char)0x0A, (char)0x09 }.Contains(chValue))
                    {
                        strValue = string.Empty;
                    }
                    else if (chValue == '<')
                    {
                        item = new SECSItem();
                        if (parent != null)
                        {
                            while (parent.Length <= parent.Count)
                                parent = parent.Parent;
                            parent.Add(item);
                        }
                        if (root == null) root = item;
                    }
                    else if (chValue == '[')
                    {
                        strValue = this.GetString(reader, ']').Replace("V", "");
                        item.Length = Convert.ToInt16(strValue);
                        strValue = string.Empty;
                    }
                    else if (chValue == '\'')
                    {
                        strValue = this.GetString(reader, '\'');
                        item.Value = strValue;
                        strValue = string.Empty;
                    }
                    else if (string.IsNullOrEmpty(item.Format))
                    {
                        strValue += chValue.ToString();
                        if (SECSLib.ItemFormat.Keys.Contains(strValue))
                        {
                            item.Format = strValue;
                            strValue = string.Empty;
                            if (SECSLib.ItemFormat[item.Format] == typeof(IList)) parent = item;
                        }
                    }
                    else
                    {
                        strValue += chValue.ToString();
                        item.Name = strValue;
                    }
                }

                root.Stream = message.ToUpper().Substring(1, message.IndexOf('F') - 1);
                root.Function = message.Replace("()", "").ToUpper().Substring(message.IndexOf('F') + 1);
                return root;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(message, ex);
                return null;
            }
        }

        private string GetString(StreamReader reader, params char[] chLast)
        {
            char chValue;
            StringBuilder sbValue = new StringBuilder();
            while (!reader.EndOfStream)
            {
                chValue = (char)reader.Read();  //.Read();
                if (chLast.Contains(chValue)) return sbValue.ToString();
                sbValue.Append(chValue);
            }

            return sbValue.ToString();
        }

        public override void SetGridHeader(GridViewEx grid)
        {
            if (grid == null) return;

            Dictionary<string, string> dicColumns = new Dictionary<string, string>();
            dicColumns.Add("DateTime", "");
            dicColumns.Add("Level", "");
            dicColumns.Add("Server", "");
            dicColumns.Add("Service", "");
            dicColumns.Add("Type", "");
            dicColumns.Add("MessageName", "");
            dicColumns.Add("Return", "");
            dicColumns.Add("Value", "");
            dicColumns.Add("LotID", "");
            dicColumns.Add("CarrierID", "");
            dicColumns.Add("EquipmentID", "");
            dicColumns.Add("PortID", "");
            dicColumns.Add("SystemByte", "");
            dicColumns.Add("ModuleID", "");
            dicColumns.Add("HostPanelID", "");
            dicColumns.Add("PanelID", "");
            dicColumns.Add("PanelQty", "");
            dicColumns.Add("TID", "");
            dicColumns.Add("Column1", "");
            dicColumns.Add("Column2", "");
            dicColumns.Add("Column3", "");
            dicColumns.Add("Column4", "");
            dicColumns.Add("Column5", "");

            string columnNames = GlobalVariable.Instance.EisParser_GridHeader;
            if (string.IsNullOrEmpty(columnNames))
            {
                StringBuilder sb = new StringBuilder();
                foreach (KeyValuePair<string, string> pair in dicColumns)
                    if (new string[] { "Service" }.Contains(pair.Key) == false) sb.Append($"{pair.Key};");
                columnNames = sb.ToString();
            }

            string columnText = string.Empty;
            foreach (string columnName in columnNames.Split(new string[] { ";" }, StringSplitOptions.RemoveEmptyEntries))
            {
                columnText = columnName;
                if (dicColumns.ContainsKey(columnName))
                {
                    if (string.IsNullOrEmpty(dicColumns[columnName]) == false) columnText = dicColumns[columnName];
                    dicColumns.Remove(columnName);
                }
                grid.AddColumn(columnName, columnText);
            }

            foreach (string columnName in dicColumns.Keys)
            {
                columnText = columnName;
                if (string.IsNullOrEmpty(dicColumns[columnName]) == false) columnText = dicColumns[columnName];
                grid.AddColumn(columnName, columnText).IsVisible = false;
            }
        }

        public override void SaveGridHeader(GridViewEx grid)
        {
            StringBuilder sb = new StringBuilder();
            foreach (GridViewColumn column in grid.Columns.OrderBy(x => x.Index))
                if (column.IsVisible) sb.AppendFormat($"{column.Name};");
            GlobalVariable.Instance.EisParser_GridHeader = sb.ToString();
            GlobalVariable.Instance.SaveSetting();
        }

        /// <summary>
        /// [CheckPoint] 로그파일 선택창을 표시한 후, 선택된 목록을 반환한다
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="args"></param>
        /// <returns></returns>
        public override LogFile[] FileSelector(FrmLogParser sender, params LogFile[] args)
        {
            FrmEqSelector dlg = null;
            try
            {
                List<LogFile> lstLogFile = new List<LogFile>();
                lstLogFile.AddRange(args);

                dlg = new FrmEqSelector();
                dlg.Owner = sender;
                dlg.Size = new System.Drawing.Size(sender.Width - 60, sender.Height - 60);
                dlg.StartPosition = FormStartPosition.CenterParent;
                dlg.ServerName = this.ServerName;
                dlg.Equipment = sender.Equipment == null ? new EisEquipment() { EquipmentID = this.EquipmentID, Server = new LogServer(this.ServerName)} : sender.Equipment;
                dlg.SelectedLogFiles = lstLogFile.ToArray();
                DialogResult dlgResult = dlg.ShowDialog();
                if (dlgResult != DialogResult.OK) return null;

                this.Account = dlg.Account;
                EisEquipment equipment = dlg.Equipment as EisEquipment;
                if (equipment == null) return null;

                sender.Equipment = equipment;
                sender.SECSDefine = dlg.SECSDefine;

                return dlg.SelectedLogFiles;
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex, true);
                return null;
            }
            finally
            {
                if (dlg != null) dlg.Dispose();
            }
        }

        #endregion


        #region [ Method : delegate object Parser() ] -------------------------

        protected Dictionary<string, StandardData> SendStandardData { get; set; } = new Dictionary<string, StandardData>();

        protected object SECS_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Server = strValue; continue; }
                    if (index == 4)
                    {
                        standardData.Type = strValue;
                        if (strValue == "TIMEOUT")
                        {
                            standardData.MessageName = $"{strValues[3]} {strValue}";
                            standardData.Return = "1";
                        }
                        continue;
                    }
                    if (index == 10) { standardData.SystemByte = $"SystemByte[{strValue}]"; continue; }
                    if (index == 11) { standardData.MessageName = strValue; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ SECS Body ] -----------------------------------------

                strLine = this.GetReadLine(reader, false);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader, false);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

                #region [ Get SECS Data ] -------------------------------------

                SECSItem rootSECS = this.GetSECSItem(standardData.MessageName, standardData.Body.ToString());
                standardData.SECSItem = rootSECS;

                if (rootSECS == null || $"S{rootSECS.Stream}F{rootSECS.Function}" != "S6F11")
                    this.LogString_Append(standardData.Body.ToString());

                SECSItem secsItem = null;
                SECSItem[] secsItems = null;
                if (rootSECS != null)
                {

                    #region [ Stream 2 ]

                    // GetData S2F23
                    if (rootSECS.Stream == "2" && rootSECS.Function == "23")
                    {
                        // TRID
                        secsItem = rootSECS.GetItemByName("TRID").FirstOrDefault();
                        if (secsItem != null) standardData.Value = $"TRID: {secsItem.Value}";

                        // TOTSMP
                        secsItem = rootSECS.GetItemByName("TOTSMP").FirstOrDefault();
                        if (secsItem != null) standardData.Value += $", TOTSMP: {secsItem.Value}";
                    }

                    // GetData S2F24
                    if (rootSECS.Stream == "2" && rootSECS.Function == "24")
                    {
                        // TRID
                        secsItem = rootSECS.GetItemByName("TIAACK").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS;
                        if (secsItem != null) standardData.Value = $"{secsItem.Value}";

                        if (new string[] { "0" }.Contains(secsItem.Value.Substring(0, 1)) == false) standardData.Return = secsItem.Value.Substring(0, 1);
                    }

                    // GetData S2F41
                    if (rootSECS.Stream == "2" && rootSECS.Function == "41")
                    {
                        // RCMD
                        secsItem = rootSECS.GetItemByName("RCMD").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS[0];
                        if (secsItem != null)
                        {
                            standardData.Value = $"RCMD: {secsItem.Value}";
                            B2_RCMD rcmdDescription = B2_RCMD.UnDefined;
                            if (Enum.TryParse<B2_RCMD>(secsItem.Value, out rcmdDescription)) standardData.Value += $" {rcmdDescription.ToString()}";
                        }

                        // LOTID
                        secsItems = rootSECS.GetItemCPValue("LOTID", "LOT_ID", "LEFT_LOTID", "RIGHT_LOTID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.LotID))
                                if (standardData.LotID.IndexOf(item.Value) >= 0) continue;
                                else standardData.LotID += ", ";
                            standardData.LotID += item.Value;
                        }

                        // EQUIPMENT_ID
                        secsItems = rootSECS.GetItemCPValue("EQUIPMENT_ID", "EquipmentID", "Equipment ID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.EquipmentID)) break; // standardData.EquipmentID += ", ";
                            standardData.EquipmentID += item.Value;
                        }

                        // CARRIER_ID
                        secsItems = rootSECS.GetItemCPValue("CARRIER_ID", "LEFT_CARRIER_ID", "RIGHT_CARRIER_ID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.CarrierID))
                                if (standardData.CarrierID.IndexOf(item.Value) >= 0) continue;
                                else standardData.CarrierID += ", ";
                            standardData.CarrierID += item.Value;
                        }

                        // PORT_ID
                        secsItems = rootSECS.GetItemCPValue("PORT_ID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.PortID)) break; // standardData.PortID += ", ";
                            standardData.PortID += item.Value;
                        }

                        this.SendStandardData.Add(standardData.SystemByte, standardData);
                    }

                    // GetData S2F42
                    if (rootSECS.Stream == "2" && rootSECS.Function == "42")
                    {
                        // RCMD
                        secsItem = rootSECS.GetItemByName("HCACK").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS[0];
                        if (secsItem != null) standardData.Value = secsItem.Value;

                        if (new string[] { "0", "4" }.Contains(secsItem.Value.Substring(0, 1)) == false) standardData.Return = secsItem.Value;
                        if (standardData?.SystemByte != null && this.SendStandardData.ContainsKey(standardData.SystemByte))
                        {
                            StandardData sendData = this.SendStandardData[standardData.SystemByte];
                            sendData.PropertiesCopy(standardData, false);
                            if (string.IsNullOrEmpty(standardData.Return)) standardData.Value = $"{standardData.Value}";
                            else standardData.Value = $"RCMD: {sendData.SECSItem[0].Value} is {standardData.Value}";
                            this.SendStandardData.Remove(standardData.SystemByte);
                        }
                    }

                    #endregion

                    #region [ Stream 6 ]

                    // GetData S6F1
                    if (rootSECS.Stream == "6" && rootSECS.Function == "1")
                    {
                        // RCMD
                        secsItem = rootSECS.GetItemByName("TRID").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS[0];
                        if (secsItem != null) standardData.Value = $"TRID: {secsItem.Value}, SMPLN: {rootSECS.ChildItems[1].Value}";
                    }

                    // GetData S6F11
                    if (rootSECS.Stream == "6" && rootSECS.Function == "11")
                    {
                        if (this.SECSDefine != null) this.SECSDefine.SetInformation(rootSECS);
                        this.LogString_Append(rootSECS.ToFullString());

                        // CEID
                        secsItem = rootSECS.GetItemByName("CEID").FirstOrDefault();
                        if (secsItem == null && rootSECS.ChildItems.Count == 3) secsItem = rootSECS[1];
                        standardData.Value = $"CEID: {secsItem.Value}" + (string.IsNullOrEmpty(secsItem.Description) ? "" : $" {secsItem.Description}");

                        // LOTID
                        secsItems = rootSECS.GetItemByName("LOT_ID", "LOTID", "LotID", "LEFT_LOTID", "RIGHT_LOTID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.LotID))
                                if (standardData.LotID.IndexOf(item.Value) >= 0) continue;
                                else standardData.LotID += ", ";
                            standardData.LotID += item.Value;
                        }

                        // EQUIPMENT_ID
                        secsItems = rootSECS.GetItemByName("EQUIPMENT_ID", "EquipmentID", "Equipment ID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.EquipmentID)) break; // standardData.EquipmentID += ", ";
                            standardData.EquipmentID += item.Value;
                        }

                        // CARRIER_ID
                        secsItems = rootSECS.GetItemByName("CARRIER_ID", "LEFT_CARRIER_ID", "RIGHT_CARRIER_ID", "BASKETID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.CarrierID))
                                if (standardData.CarrierID.IndexOf(item.Value) >= 0) continue;
                                else standardData.CarrierID += ", ";
                            standardData.CarrierID += item.Value;
                        }

                        // PORT_ID
                        secsItems = rootSECS.GetItemByName("PORT_ID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.PortID)) break; // standardData.PortID += ", ";
                            standardData.PortID += item.Value;
                        }

                        // SUBSTRATE_ID
                        secsItems = rootSECS.GetItemByName("SUBSTRATE_ID", "SUBSTRATEID", "PANELINDEX", "PANELID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.PanelID)) break; // standardData.PanelID += ", ";
                            standardData.PanelID += item.Value;
                        }

                        // HOST_SUBSTRATE_ID
                        secsItems = rootSECS.GetItemByName("HOST_SUBSTRATE_ID", "HOSTSUBSTRATEID", "MARKINGID");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.HostPanelID)) break; // standardData.HostPanelID += ", ";
                            standardData.HostPanelID += item.Value;
                        }

                        // MODULE_ID
                        secsItems = rootSECS.GetItemByName("MODULE_ID", "MODULEID", "UNIT");
                        foreach (SECSItem item in secsItems)
                        {
                            if (!string.IsNullOrEmpty(standardData.ModuleID)) standardData.HostPanelID += " ";
                            standardData.ModuleID += item.Value;
                        }

                        this.SendStandardData.Add(standardData.SystemByte, standardData);
                    }

                    // GetData S6F12
                    if (rootSECS.Stream == "6" && rootSECS.Function == "12")
                    {
                        // ACKC6
                        secsItem = rootSECS.GetItemByName("ACKC6").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS;
                        if (secsItem != null && secsItem.Value.StartsWith("0") == false)
                        {
                            standardData.Value = secsItem.Value;
                            standardData.Return = secsItem.Value.Substring(0, 1);
                        }

                        if (standardData?.SystemByte != null && this.SendStandardData.ContainsKey(standardData.SystemByte))
                        {
                            StandardData sendData = this.SendStandardData[standardData.SystemByte];
                            sendData.PropertiesCopy(standardData, false);

                            if (string.IsNullOrEmpty(standardData.Return)) standardData.Value = String.Empty;
                            else standardData.Value = $"CEID: {sendData.SECSItem[1].Value} is {standardData.Value}";
                            this.SendStandardData.Remove(standardData.SystemByte);
                        }
                    }

                    #endregion

                    #region [ Stream 7 ]

                    // GetData S7F23 : Formatted Process Program Send
                    if (rootSECS.Stream == "7" && rootSECS.Function == "23")
                    {
                        // PPID
                        secsItem = rootSECS.GetItemByName("PPID").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS[0];
                        if (secsItem != null) standardData.Value = $"PPID: {secsItem.Value}";

                        this.SendStandardData.Add(standardData.SystemByte, standardData);
                    }

                    // GetData S7F24
                    if (rootSECS.Stream == "7" && rootSECS.Function == "24")
                    {
                        // ACKC7
                        secsItem = rootSECS.GetItemByName("ACKC7").FirstOrDefault();
                        if (secsItem == null)
                        {
                            if (rootSECS.ChildItems != null && rootSECS.ChildItems.Count > 0) secsItem = rootSECS[0];
                            else secsItem = rootSECS;
                        }
                        if (secsItem != null) standardData.Value = secsItem.Value;

                        if (new string[] { "0", "6" }.Contains(secsItem.Value.Substring(0, 1)) == false) standardData.Return = secsItem.Value;
                        if (standardData?.SystemByte != null && this.SendStandardData.ContainsKey(standardData.SystemByte))
                        {
                            StandardData sendData = this.SendStandardData[standardData.SystemByte];
                            sendData.PropertiesCopy(standardData, false);
                            if (string.IsNullOrEmpty(standardData.Return)) standardData.Value = $"{standardData.Value}";
                            else standardData.Value = $"FPPS: {sendData.SECSItem[0].Value} is {standardData.Value}";
                            this.SendStandardData.Remove(standardData.SystemByte);
                        }
                    }

                    // GetData S7F25 : Formatted Process Program Request
                    if (rootSECS.Stream == "7" && rootSECS.Function == "25")
                    {
                        // PPID
                        secsItem = rootSECS.GetItemByName("PPID").FirstOrDefault();
                        if (secsItem == null) secsItem = rootSECS[0];
                        if (secsItem != null) standardData.Value = $"PPID: {secsItem.Value}";

                        this.SendStandardData.Add(standardData.SystemByte, standardData);
                    }

                    // GetData S7F26
                    if (rootSECS.Stream == "7" && rootSECS.Function == "26")
                    {
                        if (standardData?.SystemByte != null && this.SendStandardData.ContainsKey(standardData.SystemByte))
                        {
                            StandardData sendData = this.SendStandardData[standardData.SystemByte];
                            sendData.PropertiesCopy(standardData, false);
                            if (string.IsNullOrEmpty(standardData.Return)) standardData.Value = $"{standardData.Value}";
                            else standardData.Value = $"FPPD: {sendData.SECSItem[0].Value} is {standardData.Value}";
                            this.SendStandardData.Remove(standardData.SystemByte);
                        }
                    }

                    #endregion

                }

                #endregion ----------------------------------------------------

                // 응답메시지의 값이 '0'이 아닐경우에 Return에 값을 넣는다.
                if (rootSECS != null)
                {
                    int nFunction = int.Parse(rootSECS.Function);
                    if (nFunction % 2 == 0)
                    {
                        if (rootSECS.Format == "B" && string.IsNullOrEmpty(standardData.Return) && string.IsNullOrEmpty(standardData.Value))
                        {
                            if (new string[] { "0" }.Contains(rootSECS.Value.Substring(0, 1)) == false) standardData.Return = rootSECS.Value.Substring(0, 1);
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
                if (standardData != null) XLogger.Instance.Error($"{standardData.DateTime} {standardData.SystemByte}");
            }

            return standardData;
        }

        protected object PLC_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                standardData.MessageName = strValues[strValues.Length - 1].Replace("(", "").Replace(")", "");
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Server = strValue; continue; }
                    if (index == 3) { standardData.Type = strValue; continue; }
                    if (index == 6) { standardData.MessageName = strValue; continue; }
                    if (index == 8) { standardData.Value = strValue; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ PLC Body ] ------------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    if (strLine.ToUpper().StartsWith("PLC WRITE"))
                    {
                        string[] strWrites = strLine.Split(new char[] { ':', ',' }, StringSplitOptions.RemoveEmptyEntries);
                        if (strWrites.Length < 2) continue;

                        if (standardData.Type != "Write")
                        {
                            standardData.Type = "Write";
                            standardData.MessageName = "";
                        }
                        if (standardData.MessageName.Length > 0) standardData.MessageName += ", ";
                        //if (standardData.MessageName.Length > 0) standardData.MessageName += Environment.NewLine;
                        standardData.MessageName += $"{strWrites[1].Trim()}={strWrites[strWrites.Length - 1].Trim()}";
                    }
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }


        protected object MES_Parser(StreamReader reader, ref string startLine)
        {
            try
            {
                return this.Message_Parser(reader, ref startLine);
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return null;
        }

        protected object RMS_Parser(StreamReader reader, ref string startLine)
        {
            try
            {
                return this.Message_Parser(reader, ref startLine);
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return null;
        }

        protected object FDC_Parser(StreamReader reader, ref string startLine)
        {
            try
            {
                return this.Message_Parser(reader, ref startLine);
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return null;
        }

        protected object RTD_Parser(StreamReader reader, ref string startLine)
        {
            try
            {
                return this.Message_Parser(reader, ref startLine);
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return null;
        }

        protected object Message_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                Type type = typeof(StandardData);
                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                int columnIndex = 1;
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Server = strValue; continue; }
                    if (index == 3) { standardData.Service = strValue; continue; }
                    if (index == 4) { standardData.Type = strValue; continue; }
                    if (index == 5 && strValue.ToUpper().StartsWith("SYSTEMBYTE")) { standardData.SystemByte = strValue; continue; }

                    string propertyName = $"Column{columnIndex}";
                    PropertyInfo property = typeof(StandardData).GetProperty(propertyName);
                    if (property != null) { property.SetValue(standardData, strValue); columnIndex++; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (strLine != null)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                XmlDocument document = new XmlDocument();
                if (standardData.Body.Length > 4) document.LoadXml(standardData.Body.ToString());

                #endregion ----------------------------------------------------

                #region [ Get Message Data ] ----------------------------------

                if (document != null && document.ChildNodes.Count > 0)
                {
                    // KeyValuePair<Message.TagName, StandardData.PropertyName>
                    List<KeyValuePair<string, string>> keyValueList = new List<KeyValuePair<string, string>>();
                    keyValueList.Add(new KeyValuePair<string, string>("messagename", "MessageName"));
                    keyValueList.Add(new KeyValuePair<string, string>("transactionid", "TID"));
                    keyValueList.Add(new KeyValuePair<string, string>("returncode", "Return"));
                    keyValueList.Add(new KeyValuePair<string, string>("EQUIPMENTID", "EquipmentID"));
                    keyValueList.Add(new KeyValuePair<string, string>("PORTID", "PortID"));
                    keyValueList.Add(new KeyValuePair<string, string>("CARRIERID", "CarrierID"));
                    keyValueList.Add(new KeyValuePair<string, string>("LEFTCARRIERID", "CarrierID"));
                    keyValueList.Add(new KeyValuePair<string, string>("RIGHTCARRIERID", "CarrierID"));
                    keyValueList.Add(new KeyValuePair<string, string>("BASKETID", "CarrierID"));
                    keyValueList.Add(new KeyValuePair<string, string>("LOTID", "LotID"));
                    keyValueList.Add(new KeyValuePair<string, string>("HOSTPANELID", "HostPanelID"));
                    keyValueList.Add(new KeyValuePair<string, string>("MARKINGID", "HostPanelID"));
                    keyValueList.Add(new KeyValuePair<string, string>("PANELID", "PanelID"));
                    keyValueList.Add(new KeyValuePair<string, string>("PANELQTY", "PanelQty"));
                    keyValueList.Add(new KeyValuePair<string, string>("TRACEID", "Value"));
                    keyValueList.Add(new KeyValuePair<string, string>("TOTSMP", "Value"));
                    keyValueList.Add(new KeyValuePair<string, string>("SMPLN", "Value"));
                    keyValueList.Add(new KeyValuePair<string, string>("MODULEID", "ModuleID"));
                    keyValueList.Add(new KeyValuePair<string, string>("MODULE", "ModuleID"));
                    keyValueList.Add(new KeyValuePair<string, string>("UNITNO", "ModuleID"));

                    foreach (KeyValuePair<string, string> pair in keyValueList)
                    {
                        XmlNode node = document.SelectSingleNode($"//{pair.Key}");
                        if (node == null) continue;

                        PropertyInfo property = type.GetProperty(pair.Value);
                        if (property != null)
                        {
                            string orgValue = (string)property.GetValue(standardData);
                            if (!string.IsNullOrEmpty(orgValue))
                            {
                                //if (orgValue.IndexOf(node.InnerText) >= 0) continue;
                                if (!string.IsNullOrEmpty(orgValue)) orgValue = $"{orgValue}, {node.InnerText}";
                                else orgValue = node.InnerText;

                            }
                            else
                            {
                                orgValue = node.InnerText;
                            }

                            property.SetValue(standardData, orgValue);
                        }
                    }

                    // 메시지별 컬럼값 셋팅

                    if (string.Compare(standardData.MessageName, "AlarmReport") == 0)
                    {
                        XmlNode node = null;
                        node = document.SelectSingleNode($"//ALARMID");
                        if (this.HasValue(node)) standardData.Value += $"{node.InnerText}";
                        node = document.SelectSingleNode($"//ALARMSTATE");
                        if (this.HasValue(node)) standardData.Value += $" - {node.InnerText}";
                    }

                    if (string.Compare(standardData.MessageName, "ChangeEqpStatusReport") == 0)
                    {
                        XmlNode node = null; 
                        node = document.SelectSingleNode($"//CONTROLMODE");
                        if (this.HasValue(node)) standardData.Value += $"{node.InnerText}";
                        node = document.SelectSingleNode($"//CURRENTEQPSTATUS");
                        if (this.HasValue(node)) standardData.Value += $" - {node.InnerText}";
                    }

                    if (string.Compare(standardData.MessageName, "EquipmentStatusReport") == 0)
                    {
                        XmlNode node = null; 
                        node = document.SelectSingleNode($"//CONTROLMODE");
                        if (this.HasValue(node)) standardData.Value += $"{node.InnerText}";
                        node = document.SelectSingleNode($"//EQPSTATUS");
                        if (this.HasValue(node)) standardData.Value += $" - {node.InnerText}";
                        node = document.SelectSingleNode($"//CURRENTEQPSTATUS");
                        if (this.HasValue(node)) standardData.Value += $" - {node.InnerText}";
                    }

                    if (string.Compare(standardData.MessageName, "FunctionSequenceReport") == 0)
                    {
                        XmlNode node = null;
                        //node = document.SelectSingleNode($"//PANELID");
                        //if (this.HasValue(node)) standardData.Column1 += $"{node.InnerText}";
                        node = document.SelectSingleNode($"//UNIT");
                        if (this.HasValue(node)) standardData.Column1 += $"{node.InnerText}";
                        node = document.SelectSingleNode($"//UNITNO");
                        if (this.HasValue(node)) standardData.Column1 += $"_{node.InnerText}";
                        node = document.SelectSingleNode($"//SEQUENCE");
                        if (this.HasValue(node)) standardData.Column1 += $" {node.InnerText}";
                    }

                    string[] messageNames = new string[] { 
                        "CurrentRecipeIDRequestReply", "RecipeValidationRequest", "RecipeValidationRequestReply",
                        "CurrentRecipeIDRequestB2Reply", "RecipeValidationRequestB2", "RecipeValidationRequestB2Reply" };
                    foreach (string messageName in messageNames)
                    {
                        if (string.Compare(standardData.MessageName, messageName) != 0) continue;
                        XmlNode node = document.SelectSingleNode($"//RECIPEID");
                        if (node == null) continue;

                        standardData.Value = $"PPID: {node.InnerText}";
                    }



                    //if (string.Compare(standardData.MessageName, "ModuleStartReport") == 0
                    //    || string.Compare(standardData.MessageName, "ModuleEndReport") == 0
                    //    || string.Compare(standardData.MessageName, "PanelStartReport") == 0
                    //    || string.Compare(standardData.MessageName, "PanelEndReport") == 0)
                    //{
                    //    XmlNode node = document.SelectSingleNode($"//MODULEID");
                    //    if (this.HasValue(node)) standardData.Column1 += $"ModuleID: {node.InnerText}";
                    //}
                }

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        private bool HasValue(XmlNode node)
        {
            if (node == null) return false;
            
            return !string.IsNullOrWhiteSpace(node.InnerText);
        }

        protected object TIBCO_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine, "|", " ");
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                Type type = typeof(StandardData);
                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Server = strValue.Replace(':', ' ').Trim(); continue; }
                    if (index == 3) { standardData.Service = strValue; continue; }
                    if (index == 4) { standardData.Type = strValue; continue; }
                    if (index == 5) { standardData.MessageName = strValue; continue; }

                    standardData.Value += $"{strValue} ";
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (strLine != null)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------
            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        protected object TID_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                standardData.Server = $"TID";
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Type = strValue; continue; }
                    if (index == 4) { standardData.TID = strValue; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        protected object TRANSACTIONID_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                standardData.Level = $"INFO";
                standardData.Server = $"TID";
                standardData.Type = strValues[2];
                int nTID = strValues.Length - 1;
                standardData.TID = strValues[nTID];

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        /// <summary>
        /// MES, FDC, RTD T3 Timeout
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="startLine"></param>
        /// <returns></returns>
        protected object ERROR0_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                standardData.Return = "1";
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                int columnIndex = 1;
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { continue; }
                    if (index == 2) { standardData.Server = strValue; continue; }
                    if (index == 3) { standardData.Level = strValue; continue; }
                    if (index == 4) { standardData.Type += strValue; continue; }
                    if (index == 5) { standardData.Type += strValue; continue; }
                    if (index == 6) { standardData.Type += strValue; continue; }
                    if (index == 7) { continue; }
                    if (index == 8) { continue; }
                    if (index == 9) { continue; }
                    if (index == 10) { continue; }
                    if (index == 11) { continue; }
                    if (index == 12) { standardData.SystemByte = $"SystemByte[{strValue}]"; continue; }
                    if (index == 13) { standardData.MessageName = $"{strValue} {standardData.SystemByte}"; continue; }

                    string propertyName = $"Column{columnIndex}";
                    PropertyInfo property = typeof(StandardData).GetProperty(propertyName);
                    if (property != null) { property.SetValue(standardData, strValue); columnIndex++; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        /// <summary>
        /// S9F7, S9F9
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="startLine"></param>
        /// <returns></returns>
        protected object ERROR1_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                int columnIndex = 1;
                standardData.Server = strValues[2];
                standardData.Return = "1";
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 3) { standardData.Level = strValue; continue; }
                    if (index == 4) { standardData.Type = strValue; continue; }
                    if (index == 12) { standardData.SystemByte = $"SystemByte[{strValue}]"; continue; }
                    if (index == 13) { standardData.MessageName = strValue; continue; }

                    string propertyName = $"Column{columnIndex}";
                    PropertyInfo property = typeof(StandardData).GetProperty(propertyName);
                    if (property != null) { property.SetValue(standardData, strValue); columnIndex++; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

                #region [ Get SECS Data ] -------------------------------------

                SECSItem rootSECS = this.GetSECSItem(standardData.MessageName, standardData.Body.ToString());
                standardData.SECSItem = rootSECS;

                if (rootSECS != null)
                {

                    #region [ Stream 9 ]

                    // GetData S9F9
                    if (rootSECS.Stream == "9" && rootSECS.Function == "9")
                    {
                        string[] arrDec = rootSECS.Value.Split(new string[] { " " }, StringSplitOptions.RemoveEmptyEntries);
                        List<byte> lstByte = new List<byte>();

                        for (int i = 6; i < arrDec.Length; i++)
                        {
                            int nDec = int.Parse(arrDec[i]);
                            lstByte.Add((byte)nDec);
                        }
                        if (BitConverter.IsLittleEndian) lstByte.Reverse();
                        standardData.Value += $" SystemByte[{BitConverter.ToUInt32(lstByte.ToArray(), 0)}]";
                    }

                    #endregion

                }

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        /// <summary>
        /// AreYouThereRequest Time Over
        /// </summary>
        /// <param name="reader"></param>
        /// <param name="startLine"></param>
        /// <returns></returns>
        protected object ERROR2_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                standardData.Server = strValues[strValues.Length - 2];
                standardData.Level = strValues[1];
                standardData.Type = "TIMEOUT";
                standardData.MessageName = $"{strValues[strValues.Length - 6]} {strValues[strValues.Length - 5]}{strValues[strValues.Length - 4]}";
                standardData.Return = "1";
                //int columnIndex = 1;
                //for (int index = 0; index < strValues.Length; index++)
                //{
                //    string strValue = strValues[index];
                //    if (index == 0) { continue; }
                //    if (index == 1) { standardData.Level = "ERROR"; continue; }
                //    if (index == 2) { continue; }
                //    if (index == 3) { standardData.Type = strValue; continue; }
                //    if (index == 4) { continue; }
                //    if (index == 5) { standardData.MessageName = strValue; continue; }
                //    if (index == 6) { continue; }
                //    if (index == 7) { standardData.TID = strValue.Replace("◀", ""); continue; }
                //    string propertyName = $"Column{columnIndex}";
                //    PropertyInfo property = typeof(StandardData).GetProperty(propertyName);
                //    if (property != null) { property.SetValue(standardData, strValue); columnIndex++; continue; }
                //}

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        protected object EXCEPTION_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                standardData.Return = "1";
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.MessageName = strValue; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        protected object ETC_Parser(StreamReader reader, ref string startLine)
        {
            string strLine = startLine;
            StandardData standardData = null;

            try
            {
                if (string.IsNullOrWhiteSpace(strLine)) return standardData;
                if (strLine.Length < this.LogDTimeStart + this.LogDTime.Length) return standardData;
                string[] strValues = this.GetHeaderValues(strLine);
                if (strValues == null) return standardData;

                DateTime dtime = DateTime.MinValue;
                if (DateTime.TryParse(strValues[0], out dtime) == false) return standardData;

                standardData = new StandardData();
                standardData.LineNumber = this.LineNumber;
                standardData.DateTime = dtime;
                this.StandardCollection.Add(standardData);

                #region [ Header Line ] ---------------------------------------

                int columnIndex = 1;
                for (int index = 0; index < strValues.Length; index++)
                {
                    string strValue = strValues[index];
                    if (index == 0) { continue; }
                    if (index == 1) { standardData.Level = strValue; continue; }
                    if (index == 2) { standardData.Server = strValue; continue; }
                    if (index == 3) { standardData.Service = strValue; continue; }
                    if (index == 4) { standardData.Type = strValue; continue; }

                    string propertyName = $"Column{columnIndex}";
                    PropertyInfo property = typeof(StandardData).GetProperty(propertyName);
                    if (property != null) { property.SetValue(standardData, strValue); columnIndex++; continue; }
                }

                #endregion ----------------------------------------------------

                #region [ Message Body ] --------------------------------------

                strLine = this.GetReadLine(reader);
                while (string.IsNullOrWhiteSpace(strLine) == false)
                {
                    if (this.IsEnd(strLine)) break;

                    standardData.Body.AppendLine(strLine);
                    strLine = this.GetReadLine(reader);
                }
                startLine = strLine;

                #endregion ----------------------------------------------------

            }
            catch (Exception ex)
            {
                XLogger.Instance.Fatal(ex);
            }

            return standardData;
        }

        #endregion

        public enum B2_RCMD
        {
            UnDefined = 0,
            PROCESSSTART = 1,             // PROCESSSTART     
            PROCESSCANCEL = 2,            // PROCESSCANCEL     
            PROCESSABORT = 3,            // PROCESSABORT      
            PROCESSPAUSE = 4,            // PROCESSPAUSE      
            PROCESSRESUME = 5,            // PROCESSRESUME     
            CARRIERINFOSEND = 6,


            PPSELECTCOMMAND = 8,                // PPSELECTCOMMAND  
            PPSELECTCOMMAND_SPEC = 9,           // PPSELECTCOMMAND_SPC    // 사양서 Ver 1.33
            SPEC_DATA_COMMAND = 9,              // 사양서 Ver 1.34 이 후
            OPCALL = 10,             // OPCALL           
            PPSELECTCOMMANDFORBASKET = 11,      // 수직디스미어, 수직화학동 2Basket 설비를 위한 Command
            SEPARATIONCOMMAND = 21,             // SEPARATIONCOMMAND
            MERGECOMMAND = 22,             // MERGECOMMAND     

            BASKETPROCESSSTART = 23,
            BASKETPROCESSCANCEL = 24,
            BASKETINFOSEND = 25,

            SPCRESULTSEND = 26,

            CARRIERSPLITREQUEST = 31,
            CARRIERMERGEREQUEST = 32,
            CANCELRESERVECOMMAND = 33,

            CARRIERTYPESEND = 30,

            DUMMY_PROCESS_QTY = 41,

            POPUP_DATA_SEND = 42,

            HostCommand = 99,   //==To Do== Delete later For TEST
        }

    }

}
