using DevExpress.Data.Helpers;
using DevExpress.XtraBars;
using DevExpress.XtraBars.Navigation;

using System;
using System.Net;
using System.Net.Sockets;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;
using System.IO;
using System.Diagnostics;
using System.Threading;
using System.Reflection;
using System.Threading.Tasks;

using SystemX.Net.Platform.Common.ExtensionMethods;
using SystemX.Net;
using SystemX.Common;
using SystemX.Net.BaseProtocol;
using SystemX.Net.Comm;
using SystemX.Net.Schedule;
using SystemX.Net.DB.LogProcess;
using SystemX.Common.Serialization;
using SystemX.Common.Archive;

using static SystemX.Net.Platform.Common.Util.LogMessage;
using static SystemX.Net.DB.LogProcess.XLogDBConnManager;
using SystemX.Net.Platform.SystemX.Common;
using SystemX.Net.Middleware.Log.Commons;
using SystemX.Net.Platform.SystemX.Net.XEFCore.DBContext.CPXV2LogJson;

using CPXV2Log = SystemX.Net.Platform.SystemX.Net.XEFCore.DBContext.CPXV2Log;
using CPXV2LogJson = SystemX.Net.Platform.SystemX.Net.XEFCore.DBContext.CPXV2LogJson;
using Newtonsoft.Json;
using SystemX.Common.Util;
using CpTesterPlatform.CpLogUtil;

namespace SystemX.Net.MiddlewareUI
{
    public partial class MainForm : DevExpress.XtraBars.FluentDesignSystem.FluentDesignForm
    {
        static internal class CPXV2_CpLogProcessInfo
        {
            static public string strProcessDebugInfo = string.Empty;
            static public string strGetFileName = string.Empty;

            //Summary 삽입 정보 생성
            static public string strHostID = string.Empty;
            static public string strSection = string.Empty;
            static public string strStationID = string.Empty;
            static public Int64 nShortTermIdent = int.MaxValue;
            static public Int64 nLongTermIdent = int.MaxValue;
            static public string strStationName = string.Empty;
            static public string strProdNo_P = string.Empty;
            static public string strProdNo_C = string.Empty;
            static public string strTestType = string.Empty;
            static public string strTestCode = string.Empty;
            static public string strVersion = string.Empty;
            static public string strProdCode = string.Empty;
            static public string strTestListCntID = string.Empty;

            static public int nTestListFileNo = int.MaxValue;
            static public int nTestListVariantNo = int.MaxValue;
            static public int nTestListReleaseNo = int.MaxValue;

            static public string strCpLogFileComment = string.Empty;

            static public Dictionary<string, string> dicCpLogHeader = new Dictionary<string, string>();

            static public int nGetReadStepVersion = int.MaxValue;

            /*
             * CpLog Header 상 검사 시작 시간 획득 및 맨앞 공백 제거
             */
            static public string strStTime = string.Empty;

            static public long lMainMeasTime = 0;
            static public long lLongTermMeasTime = 0;
        }

        private DataTable CPXV2_MakeCpLogTable()
        {
            // Create a new DataTable titled 'Names.'
            DataTable logTable = new DataTable("CpLogProcTestResult");

            // Add three column objects to the table.
            DataColumn Column0 = new DataColumn();
            Column0.DataType = System.Type.GetType("System.Int64");
            Column0.ColumnName = "No";
            Column0.AutoIncrement = true;
            Column0.AllowDBNull = false;
            logTable.Columns.Add(Column0);

            DataColumn Column3 = new DataColumn();
            Column3.DataType = System.Type.GetType("System.Int64");
            Column3.ColumnName = "StepID";
            Column3.AllowDBNull = false;
            logTable.Columns.Add(Column3);

            DataColumn Column4 = new DataColumn();
            Column4.DataType = System.Type.GetType("System.Decimal");
            Column4.ColumnName = "MeasVal";
            Column4.AllowDBNull = true;
            logTable.Columns.Add(Column4);

            DataColumn Column5 = new DataColumn();
            Column5.DataType = System.Type.GetType("System.String");
            Column5.ColumnName = "MeasValStr";
            Column5.AllowDBNull = true;
            logTable.Columns.Add(Column5);

            DataColumn Column6 = new DataColumn();
            Column6.DataType = System.Type.GetType("System.String");
            Column6.ColumnName = "Message";
            Column6.AllowDBNull = true;
            logTable.Columns.Add(Column6);

            DataColumn Column7 = new DataColumn();
            Column7.DataType = System.Type.GetType("System.String");
            Column7.ColumnName = "GlobalMin";
            Column7.AllowDBNull = true;
            logTable.Columns.Add(Column7);

            DataColumn Column8 = new DataColumn();
            Column8.DataType = System.Type.GetType("System.String");
            Column8.ColumnName = "GlobalMax";
            Column8.AllowDBNull = true;
            logTable.Columns.Add(Column8);

            DataColumn Column9 = new DataColumn();
            Column9.DataType = System.Type.GetType("System.String");
            Column9.ColumnName = "Result";
            Column9.AllowDBNull = false;
            logTable.Columns.Add(Column9);

            DataColumn Column10 = new DataColumn();
            Column10.DataType = System.Type.GetType("System.String");
            Column10.ColumnName = "SpentTime";
            Column10.AllowDBNull = true;
            logTable.Columns.Add(Column10);

            // Create an array for DataColumn objects.
            DataColumn[] keys = new DataColumn[1];
            keys[0] = Column0;
            logTable.PrimaryKey = keys;

            // Return the new DataTable.
            return logTable;
        }

        private DataTable CPXV2_MakeProcLogTable()
        {
            // Create a new DataTable titled 'Names.'
            DataTable logTable = new DataTable("TestResult");

            // Add three column objects to the table.
            DataColumn Column0 = new DataColumn();
            Column0.DataType = System.Type.GetType("System.Int64");
            Column0.ColumnName = "No";
            Column0.AllowDBNull = false;
            logTable.Columns.Add(Column0);

            DataColumn Column1 = new DataColumn();
            Column1.DataType = System.Type.GetType("System.DateTime");
            Column1.ColumnName = "TestDT";
            Column1.AllowDBNull = true;
            logTable.Columns.Add(Column1);

            DataColumn Column2 = new DataColumn();
            Column2.DataType = System.Type.GetType("System.String");
            Column2.ColumnName = "LogData";
            Column2.AllowDBNull = false;
            logTable.Columns.Add(Column2);

            // Create an array for DataColumn objects.
            DataColumn[] keys = new DataColumn[1];
            keys[0] = Column0;
            logTable.PrimaryKey = keys;

            // Return the new DataTable.
            return logTable;
        }

        private enum eCPXV2_CreateFileInfo
        {
            SuccessSavePos = 0,
            FailedSavePos,
            MesSavePos,
            CheckLogSavePos
        }

        private string CPXV2_GetFileName(LogMappedPacket GetMappedInfo, string strCreateName)
        {
            Random randNumber = new Random();

            string strFileName = strCreateName;

            if (GetMappedInfo.objOptionFileName[0].Data.CompareTo("-") == 0)
                strFileName += @"LogFileTemp" + @randNumber.Next().ToString() + @GetMappedInfo.objOptionFileExtension[0].Data;
            else
                strFileName += @GetMappedInfo.objOptionFileName[0].Data + @GetMappedInfo.objOptionFileExtension[0].Data;

            if (File.Exists(strFileName) == true)
            {
                while (true)
                {
                    strFileName = strCreateName;

                    if (GetMappedInfo.objOptionFileName[0].Data.CompareTo("-") == 0)
                        strFileName += @"LogFileTemp" + @randNumber.Next().ToString() + @GetMappedInfo.objOptionFileExtension[0].Data;
                    else
                        strFileName += @GetMappedInfo.objOptionFileName[0].Data + "_" + @randNumber.Next().ToString() + @GetMappedInfo.objOptionFileExtension[0].Data;

                    if (File.Exists(strFileName) == false)
                        break;
                }
            }

            return strFileName;
        }

        private string CPXV2_GetFileSaveInformation(eCPXV2_CreateFileInfo fileInfo,
            LogMappedPacket GetMappedInfo,
            int iPos,
            string strMakeDate,
            bool bGetOnlyFilePath = false)
        {
            string strMakeInfo = string.Empty;
            string strMakeName = string.Empty;

            switch (fileInfo)
            {
                case eCPXV2_CreateFileInfo.SuccessSavePos:
                    strMakeInfo = LoadInfo.SERVER_SAVE_POS + @"\" + strMakeDate;
                    strMakeInfo += @"LogFileSave_ProcessPort" + (iPos + 1).ToString("D2") + "(" + GetMappedInfo.nStreamPort + ")_" + GetMappedInfo.objHost[0].Data + "_" + GetMappedInfo.objSection[0].Data + @"\";
                    break;
                case eCPXV2_CreateFileInfo.FailedSavePos:
                    strMakeInfo = LoadInfo.SERVER_SAVE_POS + @"\" + strMakeDate;
                    strMakeInfo += @"LogFileSave_ProcessPort" + (iPos + 1).ToString("D2") + "(" + GetMappedInfo.nStreamPort + ")_" + GetMappedInfo.objHost[0].Data + "_" + GetMappedInfo.objSection[0].Data + @"\ProcessingFailed\";
                    break;
                case eCPXV2_CreateFileInfo.MesSavePos:
                    strMakeInfo = LoadInfo.MES_SAVE_POS + @"\MESLogSave_ProcessPort" + (iPos + 1).ToString("D2") + "(" + GetMappedInfo.nStreamPort + ")_" + GetMappedInfo.objHost[0].Data + "_" + GetMappedInfo.objSection[0].Data + @"\";
                    strMakeInfo += strMakeDate;
                    break;
                case eCPXV2_CreateFileInfo.CheckLogSavePos:
                    strMakeInfo = LoadInfo.SERVER_SAVE_POS + @"\" + strMakeDate;
                    strMakeInfo += @"LogFileSave_ProcessPort" + (iPos + 1).ToString("D2") + "(" + GetMappedInfo.nStreamPort + ")_" + GetMappedInfo.objHost[0].Data + "_" + GetMappedInfo.objSection[0].Data + @"\LogCheck\";
                    break;
            }

            if (Directory.Exists(strMakeInfo) == false)
                Directory.CreateDirectory(strMakeInfo);

            if (bGetOnlyFilePath == false)
                strMakeName = CPXV2_GetFileName(GetMappedInfo, strMakeInfo);
            else
                strMakeName = strMakeInfo;

            return strMakeName;
        }

        private bool CPXV2_SummaryLastNoCheck(eConnCategory eConnType, ref Int64 nLastNo, ref Int64 nRowCnt)
        {
            nLastNo = 0;
            nRowCnt = 0;

            bool bResult = true;

            string strGetTableName = string.Empty;

            if (eConnType == eConnCategory.ShortTerm)
                strGetTableName = MngDBLogConn.GetDBConnectInfo().ConnShortTerm.SUMMARY_TABLE;
            else if (eConnType == eConnCategory.LongTerm)
                strGetTableName = MngDBLogConn.GetDBConnectInfo().ConnLongTerm.SUMMARY_TABLE;
            else
            {
                bResult = false;

                return bResult;
            }

            try
            {
                //Summary 테이블 현재 마지막 인덱스 번호 획득
                DataSet ds = QueryStreamProcess(eConnType, "SELECT IDENT_CURRENT('" + strGetTableName + "') AS LastNo");
                bool hasRows = XCommons.isHasRow(ds);

                //인덱스 번호 획득 실패시 예외
                if (hasRows == false)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" CPXV2 CpLogProcess Summary Table LogProcess/LastNo Query failed. [SystemX.Net.MiddlewareUI : MainForm.SummaryLastNoCheck]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    throw new Exception("[" + CPXV2_CpLogProcessInfo.strGetFileName + "] When the file is in progress.");
                }

                //인덱스 번호 변환 실패 예외
                if (Int64.TryParse(ds.Tables[0].Rows[0].ItemArray[0].ToString(), out nLastNo) == false)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                        @" CPXV2 CpLogProcess [" + strGetTableName + "] index number conversion failed failed. [SystemX.Net.MiddlewareUI : MainForm.SummaryLastNoCheck]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    throw new Exception();
                }

                if (nLastNo == 0)
                {
                    ds = QueryStreamProcess(eConnType, "SELECT ROWS FROM SYS.SYSINDEXES WHERE ID = OBJECT_ID ('" + strGetTableName + "') AND INDID < 2");

                    hasRows = XCommons.isHasRow(ds);

                    //인덱스 번호 획득 실패시 예외
                    if (hasRows == false)
                    {
                        MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" CPXV2 CpLogProcess Summary Table LogProcess/LastNo Query failed(SYS.SYSINDEXES). [SystemX.Net.MiddlewareUI : MainForm.SummaryLastNoCheck]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                        throw new Exception("[" + CPXV2_CpLogProcessInfo.strGetFileName + "] When the file is in progress(SYS.SYSINDEXES).");
                    }

                    nRowCnt = Convert.ToInt64(ds.Tables[0].Rows[0]["ROWS"]);
                }
            }
            catch
            {
                bResult = false;
            }

            return bResult;
        }

        private void RegisterCpLogComment(ref int nProcPos, DataRow[] SetMakeLogRows)
        {
            //CpLog 의 정보와 VRFY 정보를 조건에 따라 생성한 DataRow에 업데이트
            SetMakeLogRows[nProcPos]["StepID"] = "1";

            SetMakeLogRows[nProcPos]["MeasVal"] = Convert.ToDecimal(0);
            SetMakeLogRows[nProcPos]["MeasValStr"] = "";
            SetMakeLogRows[nProcPos]["Message"] = CPXV2_CpLogProcessInfo.strCpLogFileComment;

            SetMakeLogRows[nProcPos]["GlobalMin"] = "";
            SetMakeLogRows[nProcPos]["GlobalMax"] = "";

            SetMakeLogRows[nProcPos]["Result"] = "NONE";
            SetMakeLogRows[nProcPos]["SpentTime"] = "0";

            nProcPos += 1;
        }

        private void RegisterCpLogData(ref int nProcPos, DataTable SetCpLogTable, DataSet dsVRFYInfo, DataRow dr, DataRow[] SetMakeLogRows)
        {
            string strGetMeasure = string.Empty;

            //CpLog 한행의 정보 획득
            LongLogParamInfo.STEP = dr["STEP"].ToString().Trim();
            LongLogParamInfo.POSITION = dr["POSITION"].ToString().Trim();
            LongLogParamInfo.MO = dr["MO"].ToString().Trim();
            LongLogParamInfo.FNC_NAME = dr["FNC_NAME"].ToString().Trim();
            LongLogParamInfo.MIN = dr["MIN"].ToString().Trim();
            LongLogParamInfo.MEASURE = dr["MEASURE"].ToString().Trim();
            LongLogParamInfo.MAX = dr["MAX"].ToString().Trim();
            LongLogParamInfo.DIM = dr["DIM"].ToString().Trim();
            LongLogParamInfo.CHECK = dr["CHECK"].ToString().Trim();
            LongLogParamInfo.SPENT_TIME = dr["SPENT_TIME"].ToString().Trim();
            LongLogParamInfo.INFO = dr["INFO"].ToString().Trim();

            LongLogParamInfo.GLOBAL_SPEC = false;
            LongLogParamInfo.VRFY_MIN = "";
            LongLogParamInfo.VRFY_MAX = "";

            //VRFY 키 지정 검색 > 현재의 STEP 이 VRFY 에 존재하면 해당 STEP 의 정보 VRFY 에서 가져옴
            DataRow getDr = dsVRFYInfo.Tables[0].Rows.Find(LongLogParamInfo.STEP);
            if (getDr != null)
            {
                LongLogParamInfo.GLOBAL_SPEC = Convert.ToBoolean(getDr["IsGlobal"]);

                LongLogParamInfo.VRFY_MIN = getDr["SpecMin"].ToString().Trim();
                LongLogParamInfo.VRFY_MAX = getDr["SpecMax"].ToString().Trim();
            }

            //DataRow 를 설정된 DataTable Format으로 한행 생성
            SetMakeLogRows[nProcPos] = SetCpLogTable.NewRow();

            //CpLog 의 정보와 VRFY 정보를 조건에 따라 생성한 DataRow에 업데이트
            SetMakeLogRows[nProcPos]["StepID"] = LongLogParamInfo.STEP;

            SetMakeLogRows[nProcPos]["MeasVal"] = Convert.ToDecimal(0);
            SetMakeLogRows[nProcPos]["MeasValStr"] = "";
            SetMakeLogRows[nProcPos]["Message"] = "";

            if (LongLogParamInfo.FNC_NAME.IndexOf("PRINTOUT") >= 0)
            {
                if (LongLogParamInfo.MEASURE.Length > LongLogParamInfo.MessageLength)
                {
                    strGetMeasure = LongLogParamInfo.MEASURE;
                    strGetMeasure = strGetMeasure.Substring(0, LongLogParamInfo.MessageLength);

                    SetMakeLogRows[nProcPos]["Message"] = strGetMeasure;
                }
                else SetMakeLogRows[nProcPos]["Message"] = LongLogParamInfo.MEASURE;
            }
            else if (LongLogParamInfo.DIM.IndexOf("STR") >= 0 ||
            LongLogParamInfo.DIM.IndexOf("STRING") >= 0 ||
            LongLogParamInfo.DIM.IndexOf("HEX") >= 0 ||
            LongLogParamInfo.DIM.IndexOf("NONE") >= 0 ||
            LongLogParamInfo.DIM.IndexOf("BIN") >= 0 ||
            LongLogParamInfo.DIM == string.Empty)
            {
                if (LongLogParamInfo.MEASURE.Length > LongLogParamInfo.MessageValLength)
                {
                    strGetMeasure = LongLogParamInfo.MEASURE;
                    strGetMeasure = strGetMeasure.Substring(0, LongLogParamInfo.MessageValLength);

                    SetMakeLogRows[nProcPos]["MeasValStr"] = strGetMeasure;
                }
                else SetMakeLogRows[nProcPos]["MeasValStr"] = LongLogParamInfo.MEASURE;
            }
            else
            {
                //상기 케이스에 다 해당 안될때 Decimal 삽입 아무값이 없을 때 0 삽입
                if (LongLogParamInfo.MEASURE.Length <= 0)
                    SetMakeLogRows[nProcPos]["MeasVal"] = Convert.ToDecimal(0);
                else
                {
                    //Measure 존재에 대한 값변환 시도 및 실패시 String 항목으로 삽입
                    decimal getMeasValue = decimal.Zero;
                    if (Decimal.TryParse(LongLogParamInfo.MEASURE, out getMeasValue))
                        SetMakeLogRows[nProcPos]["MeasVal"] = getMeasValue;
                    else
                    {
                        //0 삽입 및 Str 에 >> 표시 및 Message 에 데이터 표시
                        SetMakeLogRows[nProcPos]["MeasVal"] = Convert.ToDecimal(0);
                        SetMakeLogRows[nProcPos]["MeasValStr"] = ">>";
                        SetMakeLogRows[nProcPos]["Message"] = LongLogParamInfo.MEASURE;
                    }
                }
            }

            //IS GLOBAL 이면 CpLog 에서 읽은 정보 삽입 아니면 VRFY 에서 읽은 정보 삽입
            if (LongLogParamInfo.GLOBAL_SPEC)
            {
                SetMakeLogRows[nProcPos]["GlobalMin"] = LongLogParamInfo.MIN;
                SetMakeLogRows[nProcPos]["GlobalMax"] = LongLogParamInfo.MAX;
            }
            else
            {
                SetMakeLogRows[nProcPos]["GlobalMin"] = LongLogParamInfo.VRFY_MIN;
                SetMakeLogRows[nProcPos]["GlobalMax"] = LongLogParamInfo.VRFY_MAX;

                if (LongLogParamInfo.VRFY_MIN.Length <= 0 &&
                    LongLogParamInfo.VRFY_MAX.Length <= 0)
                {
                    if (LongLogParamInfo.MIN.Length > 0 ||
                    LongLogParamInfo.MAX.Length > 0)
                    {
                        SetMakeLogRows[nProcPos]["GlobalMin"] = LongLogParamInfo.MIN;
                        SetMakeLogRows[nProcPos]["GlobalMax"] = LongLogParamInfo.MAX;
                    }
                }
            }

            SetMakeLogRows[nProcPos]["Result"] = LongLogParamInfo.CHECK;
            SetMakeLogRows[nProcPos]["SpentTime"] = LongLogParamInfo.SPENT_TIME;

            nProcPos += 1;
        }

        private DataRow[] CPXV2_ShortProcessMakeLogRows(int nLogCnt, DataSet dsVRFYInfo, DataTable dtLogData)
        {
            bool bMakeProcResult = true;

            DataRow[] SetMakeLogRows = new DataRow[nLogCnt];

            int nProcPos = 0;

            //CpLog 삽입할 DataTable 생성
            DataTable SetCpLogTable;
            SetCpLogTable = CPXV2_MakeCpLogTable();

            //읽은 Cplog DataTable DataRow 정보로 DataRow 업데이트 및 Datatable에 삽입
            //현재 VRFY 최근 Step 별 정보로 IsGlobal 일때 Spec 을 가져오거나 측정되어 생성된 Spec 구분하여 처리 
            string strGetMeasure = string.Empty;

            string strGetMin = string.Empty;
            string strGetMax = string.Empty;

            string strGetVRFYMin = string.Empty;
            string strGetVRFYMax = string.Empty;

            //Make Comment Step
            try
            {
                //DataRow 를 설정된 DataTable Format으로 한행 생성
                SetMakeLogRows[nProcPos] = SetCpLogTable.NewRow();

                //CpLog 의 정보와 VRFY 정보를 조건에 따라 생성한 DataRow에 업데이트
                RegisterCpLogComment(ref nProcPos, SetMakeLogRows);
            }
            catch (Exception ex)
            {
                bMakeProcResult = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" Step:" + "1 Insert log data(CpLog Comment) make failed. " + ex.Message + " [SystemX.Net.MiddlewareUI : MainForm.ProcessMakeLogRows]", ConsoleColor.Red, LogMessageLevel.FATAL);

                goto MAKE_ROW_RPCOESS_FAILED;
            }
            //
            foreach (DataRow dr in dtLogData.Rows)
            {
                try
                {
                    RegisterCpLogData(ref nProcPos, SetCpLogTable, dsVRFYInfo, dr, SetMakeLogRows);
                }
                catch (Exception ex)
                {
                    bMakeProcResult = false;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" Step:" + ShortLogParamInfo.STEP + @" Insert log data make failed. " + ex.Message + " [SystemX.Net.MiddlewareUI : MainForm.ProcessMakeLogRows]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    break;
                }
            }

            MAKE_ROW_RPCOESS_FAILED:

            if (bMakeProcResult == false)
                SetMakeLogRows = null;

            return SetMakeLogRows;
        }

        private DataRow[] CPXV2_LongProcessMakeLogRows(int nLogCnt, DataSet dsVRFYInfo, DataTable dtLogData)
        {
            bool bMakeProcResult = true;

            DataRow[] SetMakeLogRows = new DataRow[nLogCnt];

            int nProcPos = 0;

            //CpLog 삽입할 DataTable 생성
            DataTable SetCpLogTable;
            SetCpLogTable = CPXV2_MakeCpLogTable();

            //읽은 Cplog DataTable DataRow 정보로 DataRow 업데이트 및 Datatable에 삽입
            //현재 VRFY 최근 Step 별 정보로 IsGlobal 일때 Spec 을 가져오거나 측정되어 생성된 Spec 구분하여 처리 
            string strGetMeasure = string.Empty;

            string strGetMin = string.Empty;
            string strGetMax = string.Empty;

            string strGetVRFYMin = string.Empty;
            string strGetVRFYMax = string.Empty;

            //Make Comment Step
            try
            {
                //DataRow 를 설정된 DataTable Format으로 한행 생성
                SetMakeLogRows[nProcPos] = SetCpLogTable.NewRow();

                //CpLog 의 정보와 VRFY 정보를 조건에 따라 생성한 DataRow에 업데이트
                RegisterCpLogComment(ref nProcPos, SetMakeLogRows);
            }
            catch (Exception ex)
            {
                bMakeProcResult = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" Step:" + "1 Insert log data(CpLog Comment) make failed. " + ex.Message + " [SystemX.Net.MiddlewareUI : MainForm.ProcessMakeLogRows]", ConsoleColor.Red, LogMessageLevel.FATAL);

                goto MAKE_ROW_RPCOESS_FAILED;
            }
            //
            foreach (DataRow dr in dtLogData.Rows)
            {
                try
                {
                    RegisterCpLogData(ref nProcPos, SetCpLogTable, dsVRFYInfo, dr, SetMakeLogRows);
                }
                catch (Exception ex)
                {
                    bMakeProcResult = false;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" Step:" + LongLogParamInfo.STEP + @" Insert log data make failed. " + ex.Message + " [SystemX.Net.MiddlewareUI : MainForm.ProcessMakeLogRows]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    break;
                }
            }

            MAKE_ROW_RPCOESS_FAILED:

            if (bMakeProcResult == false)
                SetMakeLogRows = null;

            return SetMakeLogRows;
        }

        private void CPXV2_MakeSummaryData(int iPos, string strStationName, string strTestListID, string strHostID, string strSection,
            ref HISTLogSummary[] summaryItem)
        {
            summaryItem[0].StationName = strStationName;
            summaryItem[0].TestType = CPXV2_CpLogProcessInfo.strTestType;
            summaryItem[0].Version = CPXV2_CpLogProcessInfo.strVersion;
            summaryItem[0].ProdCode = CPXV2_CpLogProcessInfo.strProdCode;
            summaryItem[0].TestListFileNo = CPXV2_CpLogProcessInfo.nTestListFileNo;
            summaryItem[0].TestListVariantNo = CPXV2_CpLogProcessInfo.nTestListVariantNo;
            summaryItem[0].TestListCntID = strTestListID;
            summaryItem[0].StepVersion = CPXV2_CpLogProcessInfo.nGetReadStepVersion;
            summaryItem[0].Host = strHostID;
            summaryItem[0].Section = strSection;
            summaryItem[0].ProdNoC = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_C"].ToString();
            summaryItem[0].ProdNoP = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_P"].ToString();
            summaryItem[0].TestCode = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["TestCode"].ToString();
            summaryItem[0].TestListFileName = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["FileName"].ToString();
            summaryItem[0].ProductID = CPXV2_CpLogProcessInfo.dicCpLogHeader["PART_ID"];
            summaryItem[0].Result = CPXV2_CpLogProcessInfo.dicCpLogHeader["RESULT"];
            summaryItem[0].Duration = CPXV2_CpLogProcessInfo.dicCpLogHeader["DURATION"];
            summaryItem[0].TestDT = Convert.ToDateTime(CPXV2_CpLogProcessInfo.strStTime);
            //
            summaryItem[1].StationName = strStationName;
            summaryItem[1].TestType = CPXV2_CpLogProcessInfo.strTestType;
            summaryItem[1].Version = CPXV2_CpLogProcessInfo.strVersion;
            summaryItem[1].ProdCode = CPXV2_CpLogProcessInfo.strProdCode;
            summaryItem[1].TestListFileNo = CPXV2_CpLogProcessInfo.nTestListFileNo;
            summaryItem[1].TestListVariantNo = CPXV2_CpLogProcessInfo.nTestListVariantNo;
            summaryItem[1].TestListCntID = strTestListID;
            summaryItem[1].StepVersion = CPXV2_CpLogProcessInfo.nGetReadStepVersion;
            summaryItem[1].Host = strHostID;
            summaryItem[1].Section = strSection;
            summaryItem[1].ProdNoC = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_C"].ToString();
            summaryItem[1].ProdNoP = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_P"].ToString();
            summaryItem[1].TestCode = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["TestCode"].ToString();
            summaryItem[1].TestListFileName = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["FileName"].ToString();
            summaryItem[1].ProductID = CPXV2_CpLogProcessInfo.dicCpLogHeader["PART_ID"];
            summaryItem[1].Result = CPXV2_CpLogProcessInfo.dicCpLogHeader["RESULT"];
            summaryItem[1].Duration = CPXV2_CpLogProcessInfo.dicCpLogHeader["DURATION"];
            summaryItem[1].TestDT = Convert.ToDateTime(CPXV2_CpLogProcessInfo.strStTime);
        }

        private async Task<bool> CPXV2_CheckDuplicateData(eConnCategory eConnType, int iPos, string strStationName, string strHostID, string strSection, Int64 nPreNo)
        {
            DataSet dsLastSummaryInfo = null;
            DataSet dsDateTimeInfo = null;

            string strGetTableName = string.Empty;

            if(nPreNo < 0)
                return false;

            if (eConnType == eConnCategory.ShortTerm)
                strGetTableName = MngDBLogConn.GetDBConnectInfo().ConnShortTerm.SUMMARY_TABLE;
            else if (eConnType == eConnCategory.LongTerm)
                strGetTableName = MngDBLogConn.GetDBConnectInfo().ConnLongTerm.SUMMARY_TABLE;
            else
                return true;

            string strSummaryQueryText = "SELECT " +
                    "StationName, " +
                    "TestType, " +
                    "Version, " +
                    "ProdCode, " +
                    "TestListFileNo, " +
                    "TestListVariantNo, " +
                    "TestListCntID," +
                    "StepVersion, " +
                    "HostID, " +
                    "Section, " +
                    "ProdNo_C, " +
                    "ProdNo_P, " +
                    "Testcode, " +
                    "TestListFileName, " +
                    "ProductID, " +
                    "Result, " +
                    "Duration, " +
                    "TestDT " +
                    "FROM [" + strGetTableName + "] " +
                    "WHERE No = " + nPreNo.ToString() + ";";

            //직전 Summary Information 획득
            dsLastSummaryInfo = QueryStreamProcess(eConnType, strSummaryQueryText);

            if (XCommons.isHasRow(dsLastSummaryInfo) == false)
                return false;

            //직전정보와 이전정보를 비교를 위한 선언 > 검사기측 중복으로 동일 로그를 전송해도 무시 하도록
            string[] strSummaryInsertInfo = new string[18];
            string[] strSummaryBeforeInfo = new string[18];

            bool bCompareResult = false;

            try
            {
                //현재 정보중 비교할 정보 삽입
                strSummaryInsertInfo[0] = strStationName;
                strSummaryInsertInfo[1] = CPXV2_CpLogProcessInfo.strTestType;
                strSummaryInsertInfo[2] = CPXV2_CpLogProcessInfo.strVersion;
                strSummaryInsertInfo[3] = CPXV2_CpLogProcessInfo.strProdCode;
                strSummaryInsertInfo[4] = CPXV2_CpLogProcessInfo.nTestListFileNo.ToString();
                strSummaryInsertInfo[5] = CPXV2_CpLogProcessInfo.nTestListVariantNo.ToString();
                strSummaryInsertInfo[6] = CPXV2_CpLogProcessInfo.strTestListCntID.ToString();
                strSummaryInsertInfo[7] = CPXV2_CpLogProcessInfo.nGetReadStepVersion.ToString();
                strSummaryInsertInfo[8] = strHostID;
                strSummaryInsertInfo[9] = strSection;
                strSummaryInsertInfo[10] = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_C"].ToString();
                strSummaryInsertInfo[11] = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["ProdNo_P"].ToString();
                strSummaryInsertInfo[12] = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["TestCode"].ToString();
                strSummaryInsertInfo[13] = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["FileName"].ToString();
                strSummaryInsertInfo[14] = CPXV2_CpLogProcessInfo.dicCpLogHeader["PART_ID"];
                strSummaryInsertInfo[15] = CPXV2_CpLogProcessInfo.dicCpLogHeader["RESULT"];
                strSummaryInsertInfo[16] = CPXV2_CpLogProcessInfo.dicCpLogHeader["DURATION"];
                strSummaryInsertInfo[17] = CPXV2_CpLogProcessInfo.strStTime;

                //이전 정보중 비교할 정보 삽입
                strSummaryBeforeInfo[0] = dsLastSummaryInfo.Tables[0].Rows[0][0].ToString();
                strSummaryBeforeInfo[1] = dsLastSummaryInfo.Tables[0].Rows[0][1].ToString();
                strSummaryBeforeInfo[2] = dsLastSummaryInfo.Tables[0].Rows[0][2].ToString();
                strSummaryBeforeInfo[3] = dsLastSummaryInfo.Tables[0].Rows[0][3].ToString();
                strSummaryBeforeInfo[4] = dsLastSummaryInfo.Tables[0].Rows[0][4].ToString();
                strSummaryBeforeInfo[5] = dsLastSummaryInfo.Tables[0].Rows[0][5].ToString();
                strSummaryBeforeInfo[6] = dsLastSummaryInfo.Tables[0].Rows[0][6].ToString();
                strSummaryBeforeInfo[7] = dsLastSummaryInfo.Tables[0].Rows[0][7].ToString();
                strSummaryBeforeInfo[8] = dsLastSummaryInfo.Tables[0].Rows[0][8].ToString();
                strSummaryBeforeInfo[9] = dsLastSummaryInfo.Tables[0].Rows[0][9].ToString();
                strSummaryBeforeInfo[10] = dsLastSummaryInfo.Tables[0].Rows[0][10].ToString();
                strSummaryBeforeInfo[11] = dsLastSummaryInfo.Tables[0].Rows[0][11].ToString();
                strSummaryBeforeInfo[12] = dsLastSummaryInfo.Tables[0].Rows[0][12].ToString();
                strSummaryBeforeInfo[13] = dsLastSummaryInfo.Tables[0].Rows[0][13].ToString();
                strSummaryBeforeInfo[14] = dsLastSummaryInfo.Tables[0].Rows[0][14].ToString();
                strSummaryBeforeInfo[15] = dsLastSummaryInfo.Tables[0].Rows[0][15].ToString();
                strSummaryBeforeInfo[16] = dsLastSummaryInfo.Tables[0].Rows[0][16].ToString();
                strSummaryBeforeInfo[17] = dsLastSummaryInfo.Tables[0].Rows[0][17].ToString();

                int nDateTimePos = 17;
                if (strSummaryBeforeInfo[nDateTimePos].IndexOf("AM") >= 0 || strSummaryBeforeInfo[nDateTimePos].IndexOf("PM") >= 0)
                {
                    string strQueryDateTime = "SELECT DBO.XConvertDateE('" + strSummaryBeforeInfo[nDateTimePos] + "') AS 'DATETIME';";

                    dsDateTimeInfo = QueryStreamProcess(eConnType, strQueryDateTime);

                    if (XCommons.isHasRow(dsDateTimeInfo))
                    {
                        strSummaryBeforeInfo[nDateTimePos] = dsDateTimeInfo.Tables[0].Rows[0][0].ToString();

                        strSummaryBeforeInfo[nDateTimePos] = strSummaryBeforeInfo[nDateTimePos].Remove(strSummaryBeforeInfo[nDateTimePos].Length - 8, 8);
                    }
                }
                else if (strSummaryBeforeInfo[nDateTimePos].IndexOf("오전") >= 0 || strSummaryBeforeInfo[nDateTimePos].IndexOf("오후") >= 0)
                {
                    string strQueryDateTime = "SELECT DBO.XConvertDateK('" + strSummaryBeforeInfo[nDateTimePos] + "') AS 'DATETIME';";

                    dsDateTimeInfo = QueryStreamProcess(eConnType, strQueryDateTime);

                    if (XCommons.isHasRow(dsDateTimeInfo))
                    {
                        strSummaryBeforeInfo[nDateTimePos] = dsDateTimeInfo.Tables[0].Rows[0][0].ToString();

                        strSummaryBeforeInfo[nDateTimePos] = strSummaryBeforeInfo[nDateTimePos].Remove(strSummaryBeforeInfo[nDateTimePos].Length - 8, 8);
                    }
                }

                //동일 한지 비교 
                bCompareResult = strSummaryInsertInfo.SequenceEqual(strSummaryBeforeInfo);
            }
            catch
            {
                bCompareResult = true;
            }

            await Task.Delay(0);

            //True : 같다 / False : 다르다
            return bCompareResult;
        }

        private bool CPXV2_CpLogProcess(LogMappedPacket GetMappedInfo, Dictionary<string, string> dicSetLogFileInfo = null, string strSetLogFilePos = "")
        {
            int iPos = int.MinValue;

            bool bRequiredProcLogFile = false;

            if (strSetLogFilePos.Length > 0)
                bRequiredProcLogFile = true;

            if (bRequiredProcLogFile == false)
                iPos = GetMappedInfo.nNumber;
            else
                iPos = 0;

            bool bProcessResult = true;
            bool bDupLogSkipState = false;

            string strProcessDebugInfo = string.Empty;

            if (bRequiredProcLogFile == false)
            {
                strProcessDebugInfo = "[" + (iPos).ToString("D2") + "]" +
                    "[" + GetMappedInfo.nStreamPort + "]" +
                    "[" + GetMappedInfo.objHost[0].Data + "]" +
                    "[" + GetMappedInfo.objSection[0].Data + "]";
            }
            else
            {
                strProcessDebugInfo = "[" + (iPos).ToString("D2") + "]" +
                    "[FTP]" +
                    "[" + dicSetLogFileInfo["HOST"] + "]" +
                    "[" + dicSetLogFileInfo["SECTION"] + "]";
            }

            CPXV2_CpLogProcessInfo.strProcessDebugInfo = strProcessDebugInfo;

            string strMakeDate = string.Empty;

            string strSuccessFileName = string.Empty;
            string strFailedFileName = string.Empty;
            string strGetFileName = string.Empty;

            CpLogHeader getCpLogHeader = null;

            DataTable dtShortLogData = null;
            DataTable dtLongLogData = null;

            try
            {
                //파일생성 위치 및 파일명 생성
                if (bRequiredProcLogFile == false)
                {
                    strMakeDate = DateTime.Now.ToString(@"yyyy\\MM\\dd\\");

                    strSuccessFileName = CPXV2_GetFileSaveInformation(eCPXV2_CreateFileInfo.SuccessSavePos, GetMappedInfo, iPos, strMakeDate);
                    strFailedFileName = CPXV2_GetFileSaveInformation(eCPXV2_CreateFileInfo.FailedSavePos, GetMappedInfo, iPos, strMakeDate);

                    strGetFileName = Path.GetFileName(strSuccessFileName);

                    byte[] ucGetFileData = new byte[GetMappedInfo.nLogDataSize];
                    Array.Copy(GetMappedInfo.ucLogData, 0, ucGetFileData, 0, GetMappedInfo.nLogDataSize);

                    byte[] ucSetFileData = null;

                    if (GetMappedInfo.objLogType[0].Data == "RAW_SIZE")
                        ucSetFileData = XDataArchive.DecompressGZipByteToByte(ucGetFileData);
                    else if (GetMappedInfo.objLogType[0].Data == "FILE_TRANSFER")
                        ucSetFileData = XDataArchive.DecompressDeflateByteToByte(ucGetFileData);
                    else
                        throw new Exception();

                    try
                    {
                        File.WriteAllBytes(strSuccessFileName, ucSetFileData);
                    }
                    catch
                    {
                        MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" CPXV2 CpLogProcess [Log File] Create failed. - Need Hard Disk Space Check. [SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]", ConsoleColor.Red, LogMessageLevel.FATAL);

                        throw new Exception();
                    }
                }
                else
                    strSuccessFileName = strSetLogFilePos;

                //해당 CpLog 파일 읽기 및 헤더 정보 획득
                dtShortLogData = CpLogFileIO.GetLogData(strSuccessFileName, out getCpLogHeader);

                dtLongLogData = dtShortLogData.Copy();
            }
            catch
            {
                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" CPXV2 CpLogProcess Log make information failed. [SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);
            }

            try
            {
                //CpLog 파일 읽은 여부 확인
                if (dtShortLogData == null || getCpLogHeader == null)
                {
                    throw new Exception("[" + strGetFileName + "] Reading to CpLog file failed.");
                }

                CPXV2_CpLogProcessInfo.strGetFileName = strGetFileName;

                //해당 프로젝트 사용 객체 생성(Summary 생성 관련)
                CommonProtocol cp = new CommonProtocol();

                //Summary 테이블 다중 접근 방지(인덱스)
                Stopwatch stMeasTime = new Stopwatch();
                stMeasTime.Start();

                DataSet ds = null;

                bool hasRows = false;

                Int64 nSummaryRowsCount = 0;

                Int64 nShortTermLastNo = 0;
                Int64 nLongTermLastNo = 0;

                Int64 nShortTermPreNo = 0;
                Int64 nLongTermPreNo = 0;

                int nLogItemCnt = dtShortLogData.Rows.Count;
                //int iNPos = 0;

                if (CPXV2_SummaryLastNoCheck(eConnCategory.ShortTerm, ref nShortTermLastNo, ref nSummaryRowsCount) == false)
                    throw new Exception();
                else
                {
                    if (nShortTermLastNo == 0)
                        nShortTermLastNo = nSummaryRowsCount;
                    else
                        nShortTermLastNo += 1;

                    nShortTermPreNo = nShortTermLastNo - 1;
                }

                if (CPXV2_SummaryLastNoCheck(eConnCategory.LongTerm, ref nLongTermLastNo, ref nSummaryRowsCount) == false)
                    throw new Exception();
                else
                {
                    if (nLongTermLastNo == 0)
                        nLongTermLastNo = nSummaryRowsCount;
                    else
                        nLongTermLastNo += 1;

                    nLongTermPreNo = nLongTermLastNo - 1;
                }

                //Summary 삽입 정보 생성
                if (bRequiredProcLogFile == false)
                {
                    CPXV2_CpLogProcessInfo.strHostID = GetMappedInfo.objHost[0].Data.Trim();
                    CPXV2_CpLogProcessInfo.strSection = GetMappedInfo.objSection[0].Data.Trim();
                    CPXV2_CpLogProcessInfo.strStationID = getCpLogHeader.CHANNEL.Trim();
                    CPXV2_CpLogProcessInfo.nShortTermIdent = nShortTermLastNo;
                    CPXV2_CpLogProcessInfo.nLongTermIdent = nLongTermLastNo;
                    CPXV2_CpLogProcessInfo.strStationName = GetMappedInfo.objStationName[0].Data;
                    CPXV2_CpLogProcessInfo.strProdNo_P = GetMappedInfo.objProdPNo[0].Data;
                    CPXV2_CpLogProcessInfo.strProdNo_C = GetMappedInfo.objProdCNo[0].Data;
                    CPXV2_CpLogProcessInfo.strTestType = GetMappedInfo.objTestType[0].Data;
                    CPXV2_CpLogProcessInfo.strTestCode = GetMappedInfo.objTestCode[0].Data;
                    CPXV2_CpLogProcessInfo.strVersion = GetMappedInfo.objVersion[0].Data;
                    CPXV2_CpLogProcessInfo.strProdCode = GetMappedInfo.objProdCode[0].Data;
                    CPXV2_CpLogProcessInfo.nTestListVariantNo = (int)GetMappedInfo.nTestListVariantNo;
                    CPXV2_CpLogProcessInfo.strTestListCntID = GetMappedInfo.objResultTestListCntID[0].Data;
                }
                else
                {
                    CPXV2_CpLogProcessInfo.strHostID = dicSetLogFileInfo["HOST"];
                    CPXV2_CpLogProcessInfo.strSection = dicSetLogFileInfo["SECTION"];
                    CPXV2_CpLogProcessInfo.strStationID = getCpLogHeader.CHANNEL.Trim();
                    CPXV2_CpLogProcessInfo.nShortTermIdent = nShortTermLastNo;
                    CPXV2_CpLogProcessInfo.nLongTermIdent = nLongTermLastNo;
                    CPXV2_CpLogProcessInfo.strStationName = dicSetLogFileInfo["STATION_NAME"];
                    CPXV2_CpLogProcessInfo.strProdNo_P = dicSetLogFileInfo["P_TTNR"];
                    CPXV2_CpLogProcessInfo.strProdNo_C = dicSetLogFileInfo["TTNR"];
                    CPXV2_CpLogProcessInfo.strTestType = dicSetLogFileInfo["TEST_TYPE"];
                    CPXV2_CpLogProcessInfo.strTestCode = dicSetLogFileInfo["TEST_CODE"];
                    CPXV2_CpLogProcessInfo.strVersion = dicSetLogFileInfo["VERSION"];
                    CPXV2_CpLogProcessInfo.strProdCode = dicSetLogFileInfo["PROD_CODE"];
                    CPXV2_CpLogProcessInfo.nTestListVariantNo = Convert.ToInt32(dicSetLogFileInfo["VARIANT_NO"]);
                    CPXV2_CpLogProcessInfo.strTestListCntID = dicSetLogFileInfo["TESTLIST_ID"];
                }

                CPXV2_CpLogProcessInfo.dicCpLogHeader.Clear();
                CPXV2_CpLogProcessInfo.nGetReadStepVersion = int.MaxValue;

                /*
                 * CpLog Header 상 검사 시작 시간 획득 및 맨앞 공백 제거
                 */
                CPXV2_CpLogProcessInfo.strStTime = getCpLogHeader.ST_TIME.Replace("_", " ");
                CPXV2_CpLogProcessInfo.strStTime = CPXV2_CpLogProcessInfo.strStTime.Insert(CPXV2_CpLogProcessInfo.strStTime.Length - 11, "-");
                CPXV2_CpLogProcessInfo.strStTime = CPXV2_CpLogProcessInfo.strStTime.Insert(CPXV2_CpLogProcessInfo.strStTime.Length - 9, "-");
                CPXV2_CpLogProcessInfo.strStTime = CPXV2_CpLogProcessInfo.strStTime.Insert(CPXV2_CpLogProcessInfo.strStTime.Length - 4, ":");
                CPXV2_CpLogProcessInfo.strStTime = CPXV2_CpLogProcessInfo.strStTime.Insert(CPXV2_CpLogProcessInfo.strStTime.Length - 2, ":");

                if (CPXV2_CpLogProcessInfo.strStTime[0] == ' ')
                    CPXV2_CpLogProcessInfo.strStTime = CPXV2_CpLogProcessInfo.strStTime.Remove(0, 1);

                try
                {
                    //CpLog 헤더에 대한 항목 Dictionary 생성 > Summary 정보 삽입 위함
                    Type type = typeof(CpLogHeader);
                    FieldInfo[] f = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);

                    foreach (FieldInfo item in f)
                    {
                        CPXV2_CpLogProcessInfo.dicCpLogHeader.Add(item.Name.Substring(item.Name.IndexOf("<") + 1, item.Name.IndexOf(">") - item.Name.IndexOf("<") - 1)
                            , item.GetValue(getCpLogHeader).ToString().Trim());
                    }
                    //
                    CPXV2_CpLogProcessInfo.strCpLogFileComment = getCpLogHeader.COMMENT;
                }
                catch
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + strProcessDebugInfo +
                       @" CPXV2 CpLogProcess - CpLogHeader failed to create per-item for header. [SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    throw new Exception();
                }

                /*
                string strQueryTestListInformation = "SELECT A.ProdNo_C, " +
                    "B.ProdNo_P, " +
                    "D.TestCode, " +
                    "B.FileName, " +
                    "B.UseTLPosition " +
                    "FROM [PROD_Release] AS A " +
                    "INNER JOIN(SELECT X.No, X.ProdNo_P, X.TestType, X.Version, X.ProdCode, X.FileName, X.UseTLPosition, X.GroupNo " +
                    "FROM [PROD_TestList] AS X WITH(NOLOCK) WHERE X.No = " + CpLogProcessInfo.nTestListVariantNo + " " +
                    "AND TestType = '" + CpLogProcessInfo.strTestType + "' " +
                    "AND Version = '" + CpLogProcessInfo.strVersion + "' " +
                    "AND ProdCode = '" + CpLogProcessInfo.strProdCode + "') AS B " +
                    "ON B.No = " + CpLogProcessInfo.nTestListVariantNo + " " +
                    "INNER JOIN(SELECT * FROM [PROD_Group] AS Y WITH(NOLOCK)) AS C " +
                    "ON C.No = B.GroupNo " +
                    "INNER JOIN(SELECT * FROM [STAT_TestCode] AS Z WITH(NOLOCK)) AS D " +
                    "ON A.ProdNo_C = '" + CpLogProcessInfo.strProdNo_C + "' " +
                    "AND D.TestCode = '" + CpLogProcessInfo.strTestCode + "' " +
                    "AND B.No = A.TestListNo AND D.No = A.TestCodeNo;";
                */

                string strQueryTestListInformation = $"SELECT X.ProdNo_C, Z.ProdNo_P, Y.TestCode, J.FileName, Z.UseTLPosition, J.No AS 'TestListFileNo', Z.No AS 'VariantNo', J.TestType, J.Version, J.ProdCode " +
                    $"FROM [PROD_Release] AS X WITH(NOLOCK)  " +
                    $"INNER JOIN [STAT_TestCode] AS Y WITH(NOLOCK) ON X.TestCodeNo = Y.No " +
                    $"INNER JOIN [PROD_Variant] AS Z WITH(NOLOCK) ON X.VariantNo = Z.No " +
                    $"INNER JOIN [PROD_Group] AS K WITH(NOLOCK) ON Z.GroupNo = K.No " +
                    $"INNER JOIN [STOR_TestListFile] AS J WITH(NOLOCK) ON Z.TestListFileNo = J.No " +
                    $"WHERE X.VariantNo = " + CPXV2_CpLogProcessInfo.nTestListVariantNo + " " +
                    $"AND X.ProdNo_C = '" + CPXV2_CpLogProcessInfo.strProdNo_C + "' " +
                    $"AND Y.TestCode = '" + CPXV2_CpLogProcessInfo.strTestCode + "' " +
                    $"AND J.TestType = '" + CPXV2_CpLogProcessInfo.strTestType + "' " +
                    $"AND J.Version = '" + CPXV2_CpLogProcessInfo.strVersion + "' " +
                    $"AND J.ProdCode = '" + CPXV2_CpLogProcessInfo.strProdCode + "' " +
                    $"ORDER BY X.No ASC;";

                //Release 테스트리스트 정보 확인 [TestListNo] + strTestType + strTestCode + strVersion + strProdCode
                thisConnInfo[iPos].geyLatestTestListInfo = QueryStreamProcess(eConnCategory.Main, strQueryTestListInformation);

                int nLoadPosition = 0;

                if (XCommons.isHasRow(thisConnInfo[iPos].geyLatestTestListInfo))
                    nLoadPosition = Convert.ToInt32(thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["UseTLPosition"]);
                else
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                        @" CPXV2 CpLogProcess fail. Test-list cannot be searched with client information.(TestList Information) [SystemX.Net.MiddlewareUI : MainForm.CpLogProcessShortTerm]\r\n", ConsoleColor.Red, LogMessageLevel.FATAL);

                    throw new Exception();
                }

                int nGetTestListFileNo = int.MaxValue;
                int nGetTestListVariantNo = int.MaxValue;

                string strGetTestListFileNo = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["TestListFileNo"].ToString();
                string strGetTestListVariantNo = thisConnInfo[iPos].geyLatestTestListInfo.Tables[0].Rows[0]["VariantNo"].ToString();

                if (int.TryParse(strGetTestListFileNo, out nGetTestListFileNo) == false ||
                   int.TryParse(strGetTestListVariantNo, out nGetTestListVariantNo) == false)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                        @" CPXV2 CpLogProcess fail. Test-list cannot be searched with client information.(TestListFileNo or TestListVariantNo) [SystemX.Net.MiddlewareUI : MainForm.CpLogProcessShortTerm]\r\n", ConsoleColor.Red, LogMessageLevel.FATAL);

                    throw new Exception();
                }

                CPXV2_CpLogProcessInfo.nTestListFileNo = nGetTestListFileNo;
                CPXV2_CpLogProcessInfo.nTestListVariantNo = nGetTestListVariantNo;

                if (CPXV2_ReadVRFYList(iPos, CPXV2_CpLogProcessInfo.nTestListFileNo, CPXV2_CpLogProcessInfo.nTestListVariantNo, strProcessDebugInfo, out CPXV2_CpLogProcessInfo.nGetReadStepVersion, nLoadPosition, false) == false)
                    throw new Exception(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + " " + CPXV2_CpLogProcessInfo.nTestListVariantNo + " Failed ReadVRFYList()");

                //동일 할시 로그 미처리 및 리턴
                var chkDataTsk = CPXV2_CheckDuplicateData(eConnCategory.ShortTerm, iPos,
                    CPXV2_CpLogProcessInfo.strStationName,
                    CPXV2_CpLogProcessInfo.strHostID,
                    CPXV2_CpLogProcessInfo.strSection,
                    nShortTermPreNo);

                //DB 에 전송한 Summary 객체 생성
                HISTLogSummary[] summaryItem = new HISTLogSummary[2];
                summaryItem[0] = new HISTLogSummary();
                summaryItem[1] = new HISTLogSummary();

                CPXV2_MakeSummaryData(iPos,
                    CPXV2_CpLogProcessInfo.strStationName,
                    CPXV2_CpLogProcessInfo.strTestListCntID,
                    CPXV2_CpLogProcessInfo.strHostID,
                    CPXV2_CpLogProcessInfo.strSection,
                    ref summaryItem);

                Task<DataRow> tskLongTerm = null;
                //if (MngDBConn.InfoConnection.UTSI_STATE == false)

                //tskLongTerm = Task.Run(async () => await CpLogProcessLongTerm(iPos, GetMappedInfo, getCpLogHeader, dtLogData, summaryItem[1]));
                //var result = task.WaitAndUnwrapException();
                tskLongTerm = Task.Run(() => CPXV2_CpLogProcessLongTerm(iPos, nLongTermLastNo, nLongTermPreNo, getCpLogHeader, dtLongLogData, summaryItem[1]));
                //tskLongTerm = CPXV2_CpLogProcessLongTerm(iPos, GetMappedInfo, getCpLogHeader, dtLongLogData, summaryItem[1]);
                //tskLongTerm.Start();

                if (chkDataTsk.Result)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                       @" CPXV2 ShortTerm-CpLogProcess fail. Reason : ShortTerm Duplicated Before CpLog-File. [SystemX.Net.MiddlewareUI : MainForm.CpLogProcessShortTerm]\r\n", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    bDupLogSkipState = true;

                    if (tskLongTerm != null)
                        lstBulkLongTermLog.Add(tskLongTerm.Result);

                    return false;
                }

                //Summary 객체를 이용해 DB 삽입할 SqlCommand 생성
                SqlCommand cmd = cp.LogDataSummaryInsert(MngDBLogConn.GetDBConnectInfo().ConnShortTerm.SUMMARY_TABLE, summaryItem[0]);

                //Summary 삽입 > 실패시 처리 
                bProcessResult = ExcuteNonQueryStreamProcess(eConnCategory.ShortTerm, cmd);

                // TODO : SHM JSON
                /*
                try
                {
                    CpxShorTermLogJson.Instance.HIST_LogSummary.Add(new CPXV2LogJson.Tables.HIST_LogSummary
                    {
                        LogNo = nCurrentLogAccessKey,
                        LogCount = nLogItemCnt + 1,
                        StationName = summaryItem[0].StationName,
                        TestType = summaryItem[0].TestType,
                        Version = summaryItem[0].Version,
                        ProdCode = summaryItem[0].ProdCode,
                        TestListFileNo = summaryItem[0].TestListFileNo,
                        TestListVariantNo = summaryItem[0].TestListVariantNo,
                        TestListCntID = summaryItem[0].TestListCntID,
                        StepVersion = summaryItem[0].StepVersion,
                        HostID = summaryItem[0].Host,
                        Section = summaryItem[0].Section,
                        ProdNo_C = summaryItem[0].ProdNoC,
                        ProdNo_P = summaryItem[0].ProdNoP,
                        Testcode = summaryItem[0].TestCode,
                        TestListFileName = summaryItem[0].TestListFileName,
                        ProductID = summaryItem[0].ProductID,
                        Result = summaryItem[0].Result,
                        Duration = summaryItem[0].Duration,
                        TestDT = Convert.ToDateTime(CPXV2_CpLogProcessInfo.strStTime)
                    });
                    CpxShorTermLogJson.Instance.SaveChanges();

                }
                catch (Exception e)
                {
                    bProcessResult = false;
                }
                */

                if (bProcessResult == false)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + strProcessDebugInfo +
                      @" CPXV2 CpLogProcess HIST_LogSummary insert failed. [SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    //throw new Exception();
                }
                else
                {
                    //CpLog 삽입할 DataRow 생성
                    DataRow[] SetMakeLogRows = CPXV2_ShortProcessMakeLogRows(nLogItemCnt + 1, thisConnInfo[iPos].dsLatestVRFYRel, dtShortLogData);

                    if (SetMakeLogRows == null)
                        throw new Exception("<Failed CPXV2_ShortProcessMakeLogRows - SetMakeLogRows>");

                    StringBuilder ShortLogJsonSb = new StringBuilder();
                    ShortLogJsonSb.Append(JsonConvert.SerializeObject(SetMakeLogRows.Select(x => new CPXV2Log.Tables.HIST_TestResult
                    {
                        StepID = (long)x.ItemArray[1],
                        MeasVal = (decimal)x.ItemArray[2],
                        MeasValStr = x.ItemArray[3].ToString(),
                        Message = x.ItemArray[4].ToString(),
                        GlobalMin = x.ItemArray[5].ToString(),
                        GlobalMAx = x.ItemArray[6].ToString(),
                        Result = x.ItemArray[7].ToString(),
                        SpentTime = x.ItemArray[8].ToString(),
                    })).GzipCompress());

                    DataTable SetProcLogTable;
                    SetProcLogTable = CPXV2_MakeProcLogTable();

                    DataRow SetProcLogDr = SetProcLogTable.NewRow();

                    //Make Comment Step
                    try
                    {
                        SetProcLogDr["No"] = Int64.MinValue;
                        SetProcLogDr["TestDT"] = DateTime.Now;
                        SetProcLogDr["LogData"] = '-';

                        //DataRow 를 설정된 DataTable Format으로 한행 생성
                        SetProcLogDr["No"] = CPXV2_CpLogProcessInfo.nShortTermIdent;
                        SetProcLogDr["TestDT"] = Convert.ToDateTime(CPXV2_CpLogProcessInfo.strStTime);

                        if (ShortLogJsonSb.ToString().Length > 0)
                            SetProcLogDr["LogData"] = ShortLogJsonSb.ToString();
                        else
                            SetProcLogDr["LogData"] = '-';
                    }
                    catch
                    {
                        SetProcLogDr["No"] = Int64.MinValue;
                        SetProcLogDr["TestDT"] = DateTime.Now;
                        SetProcLogDr["LogData"] = '-';

                        //throw new Exception("<Failed Make JsonConvert - Json Log Row>");
                    }

                    lstBulkShortTermLog.Add(SetProcLogDr);
                }

                if (tskLongTerm != null)
                    lstBulkLongTermLog.Add(tskLongTerm.Result);

                //처리 시간 확인
                CPXV2_CpLogProcessInfo.lMainMeasTime = stMeasTime.ElapsedMilliseconds;

                if (GetMappedInfo.bShowCpLogProcessTime)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + strProcessDebugInfo +
                                @" MainTime : " + CPXV2_CpLogProcessInfo.lMainMeasTime.ToString() + ", SubTime(LongTerm) : " + CPXV2_CpLogProcessInfo.lLongTermMeasTime + " [SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]", ConsoleColor.Green, LogMessageLevel.DEBUG);
                }

                LogDataProcessText.Enqueue(new StringBuilder(">>[MainTime(ShortTerm)-MakeLogData][" + CPXV2_CpLogProcessInfo.lMainMeasTime + "][Include SubTime(LongTerm)-MakeLogData][" + CPXV2_CpLogProcessInfo.lLongTermMeasTime + "]\r\n"));
            }
            catch (Exception e)
            {
                bProcessResult = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + strProcessDebugInfo + @" CPXV2 Make CpLogProcess fail.[SystemX.Net.MiddlewareUI : MainForm.CPXV2_CpLogProcess]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
            }
            finally
            {
                if (bDupLogSkipState == false)
                {
                    if (bProcessResult)
                    {
                        if (File.Exists(strSuccessFileName))
                            File.Delete(strSuccessFileName);
                    }
                    else
                    {
                        if (bRequiredProcLogFile == false)
                        {
                            if (File.Exists(strSuccessFileName))
                                File.Copy(strSuccessFileName, strFailedFileName);
                        }
                    }
                }
            }

            return bProcessResult;
        }

        private async Task<DataRow> CPXV2_CpLogProcessLongTerm(int iPos, Int64 nLongTermNo, Int64 nLongTermPreNo, CpLogHeader getCpLogHeader, DataTable dtLogData, HISTLogSummary summaryItem)
        {
            Stopwatch stMeasTime = new Stopwatch();
            stMeasTime.Start();

            bool bProcessResult = true;

            int nLogItemCnt = dtLogData.Rows.Count;

            DataTable SetProcLogTable;
            SetProcLogTable = CPXV2_MakeProcLogTable();

            DataRow SetProcLogDr = SetProcLogTable.NewRow();

            try
            {
                SetProcLogDr["No"] = Int64.MinValue;
                SetProcLogDr["TestDT"] = DateTime.Now;
                SetProcLogDr["LogData"] = '-';

                //동일 할시 로그 미처리 및 리턴
                var chkDataTsk = CPXV2_CheckDuplicateData(eConnCategory.LongTerm, iPos,
                    CPXV2_CpLogProcessInfo.strStationName,
                    CPXV2_CpLogProcessInfo.strHostID,
                    CPXV2_CpLogProcessInfo.strSection,
                    nLongTermPreNo);

                CommonProtocol cp = new CommonProtocol();

                //Summary 객체를 이용해 DB 삽입할 SqlCommand 생성
                SqlCommand cmd = cp.LogDataSummaryInsert(MngDBLogConn.GetDBConnectInfo().ConnLongTerm.SUMMARY_TABLE, summaryItem);

                if (chkDataTsk.Result)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                       @" CPXV2 LongTerm-CpLogProcess fail. Reason : LongTerm Duplicated Before CpLog-File. [SystemX.Net.MiddlewareUI : MainForm.CpLogProcessShortTerm]\r\n", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    return SetProcLogDr;
                }

                //Summary 삽입 > 실패시 처리 
                bProcessResult = ExcuteNonQueryStreamProcess(eConnCategory.LongTerm, cmd);

                if (bProcessResult == false)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo +
                      @" CPXV2 CpLogProcess HIST_LogSummary insert failed. [SystemX.Net.MiddlewareUI : MainForm.CpLogProcessLongTerm]", ConsoleColor.Red, LogMessageLevel.FATAL);

                    throw new Exception();
                }

                //CpLog 삽입할 DataRow 생성
                DataRow[] SetMakeLogRows = CPXV2_LongProcessMakeLogRows(nLogItemCnt + 1, thisConnInfo[iPos].dsLongTermLatestVRFYRel, dtLogData);

                if (SetMakeLogRows == null)
                    throw new Exception("<Failed CPXV2_LongProcessMakeLogRows - SetMakeLogRows>");

                StringBuilder LongLogJsonSb = new StringBuilder();
                LongLogJsonSb.Append(JsonConvert.SerializeObject(SetMakeLogRows.Select(x => new CPXV2Log.Tables.HIST_TestResult
                {
                    StepID = (long)x.ItemArray[1],
                    MeasVal = (decimal)x.ItemArray[2],
                    MeasValStr = x.ItemArray[3].ToString(),
                    Message = x.ItemArray[4].ToString(),
                    GlobalMin = x.ItemArray[5].ToString(),
                    GlobalMAx = x.ItemArray[6].ToString(),
                    Result = x.ItemArray[7].ToString(),
                    SpentTime = x.ItemArray[8].ToString(),
                })).GzipCompress());

                //Make Comment Step
                try
                {
                    //DataRow 를 설정된 DataTable Format으로 한행 생성
                    SetProcLogDr["No"] = CPXV2_CpLogProcessInfo.nLongTermIdent;
                    SetProcLogDr["TestDT"] = Convert.ToDateTime(CPXV2_CpLogProcessInfo.strStTime);

                    if (LongLogJsonSb.ToString().Length > 0)
                        SetProcLogDr["LogData"] = LongLogJsonSb.ToString();
                    else
                        SetProcLogDr["LogData"] = '-';
                }
                catch
                {
                    SetProcLogDr["No"] = Int64.MinValue;
                    SetProcLogDr["TestDT"] = DateTime.Now;
                    SetProcLogDr["LogData"] = '-';

                    throw new Exception("<Failed Make JsonConvert - Json Log Row>");
                }

                //처리 시간 확인
                CPXV2_CpLogProcessInfo.lLongTermMeasTime = stMeasTime.ElapsedMilliseconds;
            }
            catch (Exception e)
            {
                bProcessResult = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + CPXV2_CpLogProcessInfo.strProcessDebugInfo + @" CPXV2 LongTerm Make CpLogProcess fail.[SystemX.Net.MiddlewareUI : MainForm.CpLogProcessLongTerm]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
            }
            finally
            {
                ;//
            }

            await Task.Delay(0);

            return SetProcLogDr;
        }
    }
}
