using System;
using System.Collections.Generic;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Runtime.Remoting.Messaging;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SystemX.Common;
using SystemX.Common.Serialization;
using SystemX.Net.BaseProtocol;
using SystemX.Net.Schedule;
using SystemX.Net.XAdaptor;
using static SystemX.Net.Platform.Common.Util.LogMessage;

namespace SystemX.Net.XAdaptor.PC
{
    public partial class XAdaptorPC
    {
        private bool Login(string strHostID, string strSection, string strTestCode, bool bUseUIM = false, bool bSimpleLookupOption = false)
        {
            if (thisConnInfo.ConnectCommandState == false)
                return false;

            try
            {
                thisConnInfo.OnCommandTime();

                try
                {
                    SYSTEM_HOST_PACKET MakeLoginPacket = new SYSTEM_HOST_PACKET();
                    int iSendSize = Marshal.SizeOf(MakeLoginPacket);
                    byte[] ucSendArray = new byte[iSendSize];
                    MakeLoginPacket = (SYSTEM_HOST_PACKET)SystemXNetSerialization.RawDeSerialize(ucSendArray, MakeLoginPacket.GetType());

                    MakeLoginPacket.bUseUIM = bUseUIM;
                    MakeLoginPacket.bUseSimpleLookupOption = bSimpleLookupOption;
                    MakeLoginPacket.objHostID[0].Data = strHostID;
                    MakeLoginPacket.objSection[0].Data = strSection;
                    MakeLoginPacket.objTestCode[0].Data = strTestCode;

                    byte[] ucSendByteInfo = XCommons.SpecialObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.HOST_INFO_CHECK), MakeLoginPacket);

                    FlowCommandControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null, false);
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                      @"Login process fail.[SystemX.Net.XAdaptor.PC - IXPCAdaptor : Login(HOST_ID,SECTION)]\r\n" +
                      ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                ;
            }

            return true;
        }

        public async Task<bool> WaitSyncTimeServer(bool bAutoApplyWinTime = true)
        {
            if (thisConnInfo.ConnectStreamState == false)
                return false;

            bool bResult = false;

            try
            {
                thisConnInfo.OnStreamTime();

                try
                {
                    TIME_PACKET MakeTimePacket = new TIME_PACKET();
                    int iSendSize = Marshal.SizeOf(MakeTimePacket);
                    byte[] ucSendArray = new byte[iSendSize];
                    MakeTimePacket = (TIME_PACKET)SystemXNetSerialization.RawDeSerialize(ucSendArray, MakeTimePacket.GetType());

                    MakeTimePacket.objMsg[0].Data = "SyncTimeRequest";

                    byte[] ucSendByteInfo = XCommons.SpecialObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.SYNC_TIME_SERVER), MakeTimePacket);

                    byte ucGetLabel = FlowStreamControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null, true);

                    thisConnInfo.OnStreamCheckTime();

                    await WaitTaskJoin(waitStreamParam, FlowStreamControl, ucGetLabel, false).ConfigureAwait(false);

                    if (QueryResult.bQueryResult)
                    {
                        if (bAutoApplyWinTime)
                        {
                            TIME_PACKET tp = (TIME_PACKET)QueryResult.xData.objData;

                            bool resultSync = COMMON.SetLocalTime(ref tp.objTime[0]);

                            if (resultSync == false)
                            {
                                int lastErrorCode = Marshal.GetLastWin32Error();

                                throw new Exception(lastErrorCode.ToString());
                            }
                        }

                        bResult = true;
                    }

                    await Task.Delay(50).ConfigureAwait(false);

                    //MessageOutput.ConsoleWrite($"Response: {responseText}, DateTime: {localDateTime}");
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                       @"[Stream Socket] Sync time-server request failed. Check time-server state. [SystemX.Net.XAdaptor.PC : XPCAdaptor.WaitSyncTimeServer]\r\n" +
                       ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                ;
            }

            return bResult;
        }

        public async Task<bool> RestoreConnAfterConfirmConn(bool bRetryAutoConnect = true)
        {
            bool bGetPingCommandResult = await SendCommandConnectState().ConfigureAwait(false);
            bool bGetPingStreamResult = await SendStreamConnectState().ConfigureAwait(false);

            bool bGetPingResult = bGetPingCommandResult && bGetPingStreamResult;

            if (bGetPingResult == false)
            {
                XAdaptorLogWrite("RestoreConnAfterConfirmConn() Ping [1] result failed.");

                if (bRetryAutoConnect)
                {
                    ComClientTryDisconnect();

                    await Task.Delay(5000);
                    //Thread.Sleep(5000);

                    ConnectStartStyleAuto = false;

                    bool bGetResult = true;
                    for (int i = 0; i < 3; i++)
                    {
                        XAdaptorLogWrite("RestoreConnAfterConfirmConn() Connection retry.");

                        bGetResult = await WaitComClientTryDistributionConnet();

                        if (bGetResult)
                            break;
                    }

                    await Task.Delay(500);

                    if (bGetResult)
                    {
                        XAdaptorLogWrite("RestoreConnAfterConfirmConn() Successful reconnection attempt.");

                        bGetPingCommandResult = await SendCommandConnectState().ConfigureAwait(false);
                        bGetPingStreamResult = await SendStreamConnectState().ConfigureAwait(false);

                        bGetPingResult = bGetPingCommandResult && bGetPingStreamResult;

                        if (bGetPingResult == false)
                            XAdaptorLogWrite("RestoreConnAfterConfirmConn() Ping [2] result failed.");
                    }
                    else
                        XAdaptorLogWrite("RestoreConnAfterConfirmConn() Reconnection attempt failed.");
                }
            }

            return bGetPingResult;
        }

        public bool SetCustomPacket(params string[] strSetInfo)
        {
            if (thisConnInfo.ConnectCommandState == false)
                return false;
            if (thisConnInfo.InitialInfoState == false)
                return false;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return false;

            //Temp Exception - 파라미터 임시 고정
            if (strSetInfo.Length != 5)
                return false;

            bool bStatus = true;

            try
            {
                try
                {
                    USER_PACKET CustomPacket = new USER_PACKET();
                    int iSizeCustomPacket = Marshal.SizeOf(CustomPacket);
                    byte[] ucCustomPacketArray = new byte[iSizeCustomPacket];
                    CustomPacket = (USER_PACKET)SystemXNetSerialization.RawDeSerialize(ucCustomPacketArray, CustomPacket.GetType());

                    string strCommand = strSetInfo[0];
                    string strTableName = strSetInfo[1];

                    int iColLength = 0;
                    int.TryParse(strSetInfo[2], out iColLength);

                    if (iColLength == 0)
                        throw new Exception();

                    //임시 : 최소 컬럼 사이즈
                    if (iColLength < 6)
                        throw new Exception();

                    string strColName = strSetInfo[3];
                    string strColData = strSetInfo[4];

                    if ((strColName.Split(',').Count() != iColLength) ||
                        (strColData.Split(',').Count() != iColLength))
                        throw new Exception();

                    //"ProcNo,PalletNumber,PalletID,PIndex,ProdNo,ProdID,SensorType,Status,TestID,Result";
                    CustomPacket.objProcessInfo[0].objProdNo_C[0].Data = "";
                    CustomPacket.objProcessInfo[0].objTestType[0].Data = "";
                    CustomPacket.objProcessInfo[0].objTestCode[0].Data = "";
                    CustomPacket.objProcessInfo[0].objTestListFileVersion[0].Data = "";
                    CustomPacket.objProcessInfo[0].objProductionCode[0].Data = "";
                    CustomPacket.objProcessInfo[0].objProductID[0].Data = "";

                    CustomPacket.objTableCommand[0].Data = strCommand;
                    CustomPacket.objTableName[0].Data = strTableName;
                    CustomPacket.uiSubLength = (uint)iColLength;
                    CustomPacket.objNames[0].Data = strColName;
                    CustomPacket.objDatas[0].Data = strColData;
                    CustomPacket.objCommandResult[0].Data = "-";

                    ucCustomPacketArray = XCommons.SpecialObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.ETC), CustomPacket);

                    FlowCommandControl.InsertSendQueue(DateTime.Now, ucCustomPacketArray, null);
                }
                catch (Exception e)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                        @"Send SetCustomPacket packet failed [" + e.Message + "]" +
                        "[SystemX.Net.XAdaptor.PC : XPCAdaptor.SetCustomPacket]\r\n", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    bStatus = false;
                }
                finally
                {

                }
            }
            finally
            {
                ;
            }

            return bStatus;
        }

        private byte SendTestListPacket(BASE_PROTOCOL bp, uint nStationID, string strProdNo_C,
            string strTestType,
            string strTestCode,
            string strTestListVersion,
            string strProductionCode)
        {
            PROCESS_PACKET MakeProcessPacket = new PROCESS_PACKET();
            int iSendSize = Marshal.SizeOf(MakeProcessPacket);
            byte[] ucSendArray = new byte[iSendSize];
            MakeProcessPacket = (PROCESS_PACKET)SystemXNetSerialization.RawDeSerialize(ucSendArray, MakeProcessPacket.GetType());

            MakeProcessPacket.nStationID = nStationID;
            MakeProcessPacket.objProdNo_C[0].Data = strProdNo_C;
            MakeProcessPacket.objTestType[0].Data = strTestType;
            MakeProcessPacket.objTestCode[0].Data = strTestCode;
            MakeProcessPacket.objTestListFileVersion[0].Data = strTestListVersion;
            MakeProcessPacket.objProductionCode[0].Data = strProductionCode;
            MakeProcessPacket.objProductID[0].Data = "";

            byte[] ucSendByteInfo = XCommons.SpecialObjectToByteStream(bp, MakeProcessPacket);

            return FlowCommandControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null, PacketFlowControl.TestListResultToken, false);
        }

        public async Task<bool> AsyncWaitCheckTestList(uint nStationID, string strProdNo_C,
            string strTestType,
            string strTestCode,
            string strTestListVersion,
            string strProductionCode)
        {
            if (thisConnInfo.ConnectCommandState == false)
                return false;
            if (thisConnInfo.InitialInfoState == false)
                return false;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return false;

            bool bResult = false;

            try
            {
                thisConnInfo.OnCommandTime();

                try
                {
                    for (int i = 0; i < COMM_RETRY; i++)
                    {
                        byte ucGetLabel = SendTestListPacket(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.PROCESS_QUERY, BASE_PROTOCOL.OPTION_CODE.CHECK_VAILD_TESTLIST),
                             nStationID,
                             strProdNo_C,
                             strTestType,
                             strTestCode,
                             strTestListVersion,
                             strProductionCode);

                        await WaitTaskJoin(waitStreamParam, FlowStreamControl, ucGetLabel).ConfigureAwait(false);

                        if (QueryResult.bQueryResult)
                        {
                            if (XCommons.isHasRow(CurrentTestList().getTestListDataSet()))
                                bResult = true;

                            break;
                        }

                        await Task.Delay(50).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    bResult = false;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                      @"Wait TestList - Release List Lookup Attempt Error. [SystemX.Net.XAdaptor.PC - IXPCAdaptor : WaitQueryTestList]\r\n" +
                      ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                await Task.Delay(50).ConfigureAwait(false);
            }

            return bResult;
        }

        public bool QueryTestList(uint nStationID, string strProdNo_C,
            string strTestType,
            string strTestCode,
            string strTestListVersion,
            string strProductionCode)
        {
            if (thisConnInfo.ConnectCommandState == false)
                return false;
            if (thisConnInfo.InitialInfoState == false)
                return false;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return false;

            try
            {
                thisConnInfo.OnCommandTime();

                try
                {
                    SendTestListPacket(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.PROCESS_QUERY, BASE_PROTOCOL.OPTION_CODE.QUERY_TESTLIST),
                        nStationID,
                        strProdNo_C,
                        strTestType,
                        strTestCode,
                        strTestListVersion,
                        strProductionCode);
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                      @"TestList - Release List Lookup Attempt Error. [SystemX.Net.XAdaptor.PC - IXPCAdaptor : QueryTestList]\r\n" +
                      ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                ;
            }

            return true;
        }

        public async Task<Tuple<string, int>> GetTestListQueryWithFilePath(string strMakePath, uint nStationID, string strProdNo_C,
         string strTestType,
         string strTestCode,
         string strTestListVersion,
         string strProductionCode,
         bool bCheckAfter = false)
        {
            string strGetMakeFilePath = string.Empty;
            int nGetTestListNum = int.MinValue;

            bool bCheckResult = true;
            bool bFindResult = true;

            if (bCheckAfter == false)
                goto QUERY_TESTLIST;

            bCheckResult = await AsyncWaitCheckTestList(nStationID, strProdNo_C,
                  strTestType,
                  strTestCode,
                  strTestListVersion,
                  strProductionCode);

            if (bCheckResult == false)
                return new Tuple<string, int>(strGetMakeFilePath, nGetTestListNum);

QUERY_TESTLIST:

            for (int n = 0; n < 2; n++)
            {
                bFindResult = true;

                if (await AsyncWaitQueryTestList(nStationID, strProdNo_C,
                    strTestType,
                    strTestCode,
                    strTestListVersion,
                    strProductionCode) == false)
                    continue;

                mgrPRODTestList.GetPRODTestList("", strProdNo_C, strTestType, strTestCode, strTestListVersion, strProductionCode);

                //검색되는 정보가 존재시
                if (mgrPRODTestList.GetCurrentTestListRow() == null || mgrPRODTestList.GetCurrentTestListRow().Count() != 1)
                    continue;

                nGetTestListNum = Convert.ToInt32(mgrPRODTestList.GetCurrentTestListRow()[0]["TestListNo"].ToString());

                //해당위치 생성된 테스트리스트 파일 경로 및 파일명 반환
                strGetMakeFilePath = mgrPRODTestList.MakeTestListFile(strMakePath);

                await Task.Delay(10).ConfigureAwait(false);

                try
                {
                    DataSet dsReadXml = new DataSet();
                    dsReadXml.ReadXml(strGetMakeFilePath);
                    DataTable dtReadXml = new DataTable();
                    dtReadXml = dsReadXml.Tables[0];
                }
                catch (Exception ex)
                {
                    strGetMakeFilePath = string.Empty;

                    nGetTestListNum = int.MinValue;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                         @"Test-list internal check error. [SystemX.Net.XAdaptor.PC - IXPCAdaptor : GetTestListQueryWithFilePath]\r\n" +
                         ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    bFindResult = false;
                }
                finally
                {
                    await Task.Delay(100).ConfigureAwait(false);
                }

                if (bFindResult)
                    break;
            }

            return new Tuple<string, int>(strGetMakeFilePath, nGetTestListNum);
        }

        public async Task<bool> AsyncWaitQueryTestList(uint nStationID, string strProdNo_C,
            string strTestType,
            string strTestCode,
            string strTestListVersion,
            string strProductionCode)
        {
            if (thisConnInfo.ConnectCommandState == false)
                return false;
            if (thisConnInfo.InitialInfoState == false)
                return false;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return false;

            bool bResult = false;

            try
            {
                thisConnInfo.OnCommandTime();

                try
                {
                    for (int i = 0; i < COMM_RETRY; i++)
                    {
                        byte ucGetLabel = SendTestListPacket(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.PROCESS_QUERY, BASE_PROTOCOL.OPTION_CODE.QUERY_TESTLIST),
                             nStationID,
                             strProdNo_C,
                             strTestType,
                             strTestCode,
                             strTestListVersion,
                             strProductionCode);

                        await WaitTaskJoin(waitStreamParam, FlowStreamControl, ucGetLabel).ConfigureAwait(false);

                        if (QueryResult.bQueryResult)
                        {
                            if (XCommons.isHasRow(CurrentTestList().getTestListDataSet()))
                                bResult = true;

                            break;
                        }

                        await Task.Delay(50).ConfigureAwait(false);
                    }
                }
                catch (Exception ex)
                {
                    bResult = false;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") +
                      @"Wait TestList - Release List Lookup Attempt Error. [SystemX.Net.XAdaptor.PC - IXPCAdaptor : AsyncWaitQueryTestList]\r\n" +
                      ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
                finally { }
            }
            finally
            {
                await Task.Delay(50).ConfigureAwait(false);
            }

            return bResult;
        }

        private eFileSendRecvResult CPLogFileTransfer(string strFilePos, bool bResultWait = true, ushort usPalletIndex = 0)
        {
            if (thisConnInfo.ConnectStreamState == false)
                return eFileSendRecvResult.StreamSocketNoConnect;
            if (thisConnInfo.InitialInfoState == false)
                return eFileSendRecvResult.ConnectInitializeFail;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return eFileSendRecvResult.ConnectInitializeFail;

            eFileSendRecvResult sendrecvResult = eFileSendRecvResult.None;

            bool bLockToken = false;

            try
            {
                thisConnInfo.OnStreamTime();

                //File Access Check
                FileStream fs = null;
                try
                {
                    Thread.Sleep(FILE_ACCESS_WAITTIME);

                    fs = new FileStream(strFilePos, FileMode.Open, FileAccess.Read);

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }
                }
                catch (Exception ex)
                {
                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file access check fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    sendrecvResult = eFileSendRecvResult.FileAccessError;
                }
                finally
                {
                    if (sendrecvResult == eFileSendRecvResult.None)
                    {
                        try
                        {
                            if (bResultWait)
                                FlowStreamControl.STM.GetLabel(PacketFlowControl.TransferResultToken);

                            //FileProcess
                            int iSize = File.ReadAllBytes(strFilePos).Length;
                            byte[] ucSendByteInfo = null;

                            if (iSize > SystemXNetSerialization.MAX_PACKET_SIZE)
                            {
                                //sendrecvResult = FileSendRecvResult.FileSizeOver;

                                List<byte[]> getStreamList = XCommons.ObjectToByteStreamList(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.RAW_SIZE), strFilePos);

                                if (getStreamList.Count() > 0)
                                {
                                    DateTime dtSendTime = DateTime.Now;
                                    for (int i = 0; i < getStreamList.Count(); i++)
                                    {
                                        if (FlowStreamControl.InsertSendQueue(dtSendTime, getStreamList.ElementAt(i), null, false, true, true) == PacketFlowControl.CommonErrCode)
                                            throw new Exception();
                                    }
                                }
                            }
                            else
                            {
                                ucSendByteInfo = XCommons.ObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.FILE_TRANSFER), strFilePos);

                                if (FlowStreamControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null) == PacketFlowControl.CommonErrCode)
                                    throw new Exception();
                            }

                            if (bResultWait)
                                WaitThreadJoin(waitStreamParam, FlowStreamControl, PacketFlowControl.TransferResultToken, false);
                        }
                        catch (Exception ex)
                        {
                            MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file read and queue control insert fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                            sendrecvResult = eFileSendRecvResult.FileProcFailed;
                        }
                    }
                }
            }
            finally
            {
                if (bResultWait)
                    FlowStreamControl.STM.ClearLabel(PacketFlowControl.TransferResultToken);
            }

            if (bResultWait)
            {
                if (QueryResult.bFileRecvResult == false)
                    sendrecvResult = eFileSendRecvResult.FileProcFailed;
                else
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;
            }
            else
            {
                if (sendrecvResult == eFileSendRecvResult.None)
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;
            }

            FILE_FAILED_BACKUP:

            if (sendrecvResult != eFileSendRecvResult.FileProcSuccess)
            {

            }

            return sendrecvResult;
        }

        public async Task<eFileSendRecvResult> AsyncCPLogFileTransfer(string strFilePos,
           string targetStationName,
           int targetTestListNo,
           string targetProcNo_P,
           string targetProcNo_C,
           string targetTestType,
           string targetTestCode,
           string targetVersion,
           string targetProdCode)
        {
            stFileSendTime.Restart();

            //Date Info
            string strYYYY = string.Empty;
            string strMM = string.Empty;
            string strdd = string.Empty;

            DateTime dtSet = DateTime.Now;
            strYYYY = dtSet.ToString("yyyy");
            strMM = dtSet.ToString("MM");
            strdd = dtSet.ToString("dd");
            //
            eFileSendRecvResult sendrecvResult = eFileSendRecvResult.None;

            //TestListCntID
            string strGetCurrentTestListID = (mgrPRODTestList as TProdTestListInfo).GetTestListCntID();

            string strSetBackupInfo = targetStationName + ";" +
                 targetTestListNo + ";" +
                 targetProcNo_P + ";" +
                 targetProcNo_C + ";" +
                 targetTestType + ";" +
                 targetTestCode + ";" +
                 targetVersion + ";" +
                 targetProdCode + ";" +
                 strGetCurrentTestListID;

            string strSetBackupFilePos = strFilePos;
            string strSetBackupFileName = Path.GetFileName(strFilePos);

            byte[] ucSetBackupFileData = null;

            //File Access Check
            Stopwatch stWaitSendTime = new Stopwatch();
            stWaitSendTime.Start();

            bool bFileAccessSuccess = false;
            string strLastErrMsg = string.Empty;

            await Task.Delay(50).ConfigureAwait(false);

            while (true)
            {
                if (bFileAccessSuccess)
                    break;

                if (stWaitSendTime.ElapsedMilliseconds > OBJECT_ACCESS_WAITTIME)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file access check fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + strLastErrMsg, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    sendrecvResult = eFileSendRecvResult.FileAccessError;

                    break;
                }

                FileStream fs = null;
                try
                {
                    await Task.Delay(FILE_ACCESS_WAITTIME).ConfigureAwait(false);

                    fs = new FileStream(strFilePos, FileMode.Open, FileAccess.Read);

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }

                    ucSetBackupFileData = File.ReadAllBytes(strFilePos);

                    bFileAccessSuccess = true;
                }
                catch (Exception ex)
                {
                    strLastErrMsg = ex.Message;

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }
                }

                await Task.Delay(OBJECT_ACCESS_CHECKTIME).ConfigureAwait(false);
            }
            //
            if (thisConnInfo.ConnectStreamState == false)
                sendrecvResult = eFileSendRecvResult.StreamSocketNoConnect;
            if (thisConnInfo.InitialInfoState == false)
                sendrecvResult = eFileSendRecvResult.ConnectInitializeFail;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                sendrecvResult = eFileSendRecvResult.ConnectInitializeFail;

            if (sendrecvResult != eFileSendRecvResult.None)
                goto FILE_FAILED_BACKUP;

            if (stBackupFileSendTime.ElapsedMilliseconds < OBJECT_ACCESS_WAITTIME)
            {
                await Task.Delay((int)(OBJECT_ACCESS_WAITTIME - stBackupFileSendTime.ElapsedMilliseconds)).ConfigureAwait(false);
            }

            bool bObjGetLock = false;

            try
            {
                Stopwatch stSmpCheckTime = new Stopwatch();
                stSmpCheckTime.Start();

                while (true)
                {
                    //Force Release 5s wait after smp
                    if (stSmpCheckTime.ElapsedMilliseconds >= OBJECT_ACCESS_WAITTIME)
                    {
                        if (_smpSlim.CurrentCount <= 0)
                        {
                            try
                            {
                                _smpSlim.Release();
                            }
                            catch
                            {
                                ;//smp release lock exception
                            }
                        }

                        stSmpCheckTime.Restart();
                    }
                    //
                    //if (bTaskSubLockState == false)
                    {
                        //Backup File Proc wait
                        bObjGetLock = await _smpSlim.WaitAsync(100);

                        if (bObjGetLock)
                            break;
                    }
                }

                thisConnInfo.OnStreamTime();

                if (sendrecvResult == eFileSendRecvResult.None)
                {
                    // TODO : FTP ALIS 
                    if (LoadInfo.FTP_Use)
                    {
                        if(ControlFTP.FTPConnState)
                        {
                            string strSetSendFTPInfo = strSetBackupInfo;

                            strSetSendFTPInfo += (";" + LoadInfo.HOST_ID);
                            strSetSendFTPInfo += (";" + LoadInfo.SECTION);

                            XAdaptorFileLogWrite(eSetFileLogCategory.FTPFileLog, strYYYY, strMM, strdd, strSetSendFTPInfo, strSetBackupFileName, "LogFileSend[FTP]>Try");

                            string strSetFilePos = MakeZipIncludeInfoCpLog(strSetSendFTPInfo, strSetBackupFilePos, strSetBackupFileName, ucSetBackupFileData);

                            if (ControlFTP.FileUpload(strSetFilePos))
                            {
                                XAdaptorFileLogWrite(eSetFileLogCategory.FTPFileLog, strYYYY, strMM, strdd, strSetSendFTPInfo, strSetBackupFileName, "LogFileSend[FTP]>Result>Success");

                                if (File.Exists(strSetFilePos))
                                    File.Delete(strSetFilePos);
                                //string strGetFileName = Path.GetFileName(strSetFilePos);
                                //string ss = await ControlFTP.FileDownload(strGetFileName, @"D:\");

                                return eFileSendRecvResult.FileProcSuccess;
                            }
                            else
                            {
                                XAdaptorFileLogWrite(eSetFileLogCategory.FTPFileLog, strYYYY, strMM, strdd, strSetSendFTPInfo, strSetBackupFileName, "LogFileSend[FTP]>Result>Failed");
                                XAdaptorFileLogWrite(eSetFileLogCategory.FTPFileLog, strYYYY, strMM, strdd, strSetSendFTPInfo, strSetBackupFileName, "LogFileSend[FTP]>Try By Socket");
                            }
                        }
                    }

                    try
                    {
                        FlowStreamControl.STM.GetLabel(PacketFlowControl.TransferResultToken);

                        CP_PACKET setCPPacket = new CP_PACKET();
                        int iPacketSize = Marshal.SizeOf(setCPPacket);
                        byte[] ucPacketMake = new byte[iPacketSize];
                        setCPPacket = (CP_PACKET)SystemXNetSerialization.RawDeSerialize(ucPacketMake, setCPPacket.GetType());

                        setCPPacket.objStationName[0].Data = targetStationName;
                        setCPPacket.objProdNo_P[0].Data = targetProcNo_P;
                        setCPPacket.objProdNo_C[0].Data = targetProcNo_C;
                        setCPPacket.objTestType[0].Data = targetTestType;
                        setCPPacket.objTestCode[0].Data = targetTestCode;
                        setCPPacket.objVersion[0].Data = targetVersion;
                        setCPPacket.objProdCode[0].Data = targetProdCode;
                        setCPPacket.uiTestListNo = (uint)targetTestListNo;

                        XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY, strMM, strdd, strSetBackupInfo, strSetBackupFileName, "LogFileSend>Try");

                        //FileProcess
                        int iSize = File.ReadAllBytes(strFilePos).Length;
                        byte[] ucSendByteInfo = null;

                        if (iSize > SystemXNetSerialization.MAX_PACKET_SIZE)
                        {
                            List<byte[]> getStreamList = XCommons.ObjectToByteStreamList(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.RAW_SIZE), strFilePos, setCPPacket);

                            if (getStreamList.Count() > 0)
                            {
                                DateTime dtSendTime = DateTime.Now;
                                for (int i = 0; i < getStreamList.Count(); i++)
                                {
                                    if (FlowStreamControl.InsertSendQueue(dtSendTime, getStreamList.ElementAt(i), null, false, true, true) == PacketFlowControl.CommonErrCode)
                                        throw new Exception();
                                }
                            }
                        }
                        else
                        {
                            ucSendByteInfo = XCommons.ObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.FILE_TRANSFER), strFilePos, setCPPacket);

                            if (FlowStreamControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null) == PacketFlowControl.CommonErrCode)
                                throw new Exception();
                        }

                        await WaitTaskJoin(waitStreamParam, FlowStreamControl, PacketFlowControl.TransferResultToken, false).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file read and queue control insert fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                        sendrecvResult = eFileSendRecvResult.FileProcFailed;

                        XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY, strMM, strdd, strSetBackupInfo, strSetBackupFileName, "LogFileSend>TryCatch>Failed");
                    }
                }
            }
            finally
            {
                FlowStreamControl.STM.ClearLabel(PacketFlowControl.TransferResultToken);

                if (bObjGetLock)
                {
                    try
                    {
                        _smpSlim.Release();
                    }
                    catch
                    {
                        ;//smp release lock exception
                    }

                    bObjGetLock = false;
                }
            }

            //TODO : For Debug Test
            //QueryResult.bFileRecvResult = false;

            if (sendrecvResult == eFileSendRecvResult.None)
            {
                if (QueryResult.bFileRecvResult == false)
                {
                    sendrecvResult = eFileSendRecvResult.FileProcFailed;

                    XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY, strMM, strdd, strSetBackupInfo, strSetBackupFileName, "LogFileSend>Result>Failed");
                }
                else
                {
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;

                    XAdaptorFileLogWrite(eSetFileLogCategory.FileLog, strYYYY, strMM, strdd, strSetBackupInfo, strSetBackupFileName, "LogFileSend>Result>Success");
                }
            }

            FILE_FAILED_BACKUP:

            if (sendrecvResult != eFileSendRecvResult.FileProcSuccess)
                XAdaptorFailedFileBackupProc(sendrecvResult, strSetBackupInfo, strSetBackupFilePos, strSetBackupFileName, ucSetBackupFileData);
            
            return sendrecvResult;
        }

        private async Task<eFileSendRecvResult> AsyncFailedLogFileTransfer(string strFilePos,
           string targetStationName,
           int targetTestListNo,
           string targetProcNo_P,
           string targetProcNo_C,
           string targetTestType,
           string targetTestCode,
           string targetVersion,
           string targetProdCode,
           string targetTestListID)
        {
            eFileSendRecvResult sendrecvResult = eFileSendRecvResult.None;

            //File Access Check
            Stopwatch stWaitSendTime = new Stopwatch();
            stWaitSendTime.Start();

            bool bFileAccessSuccess = false;
            string strLastErrMsg = string.Empty;
            while (true)
            {
                if (bFileAccessSuccess)
                    break;

                if (stWaitSendTime.ElapsedMilliseconds > OBJECT_ACCESS_WAITTIME)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file access check fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + strLastErrMsg, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    sendrecvResult = eFileSendRecvResult.FileAccessError;

                    break;
                }

                FileStream fs = null;
                try
                {
                    await Task.Delay(FILE_ACCESS_WAITTIME).ConfigureAwait(false);

                    fs = new FileStream(strFilePos, FileMode.Open, FileAccess.Read);

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }

                    bFileAccessSuccess = true;
                }
                catch (Exception ex)
                {
                    strLastErrMsg = ex.Message;

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }
                }

                await Task.Delay(OBJECT_ACCESS_CHECKTIME).ConfigureAwait(false);
            }
            //
            if (thisConnInfo.ConnectStreamState == false)
                sendrecvResult = eFileSendRecvResult.StreamSocketNoConnect;
            if (thisConnInfo.InitialInfoState == false)
                sendrecvResult = eFileSendRecvResult.ConnectInitializeFail;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                sendrecvResult = eFileSendRecvResult.ConnectInitializeFail;

            if (sendrecvResult != eFileSendRecvResult.None)
                goto FILE_FAILED_BACKUP;

            try
            {
                thisConnInfo.OnStreamTime();

                if (sendrecvResult == eFileSendRecvResult.None)
                {
                    try
                    {
                        FlowStreamControl.STM.GetLabel(PacketFlowControl.TransferResultToken);

                        CP_PACKET setCPPacket = new CP_PACKET();
                        int iPacketSize = Marshal.SizeOf(setCPPacket);
                        byte[] ucPacketMake = new byte[iPacketSize];
                        setCPPacket = (CP_PACKET)SystemXNetSerialization.RawDeSerialize(ucPacketMake, setCPPacket.GetType());

                        setCPPacket.objStationName[0].Data = targetStationName + ";@#$%;TFL";
                        setCPPacket.objProdNo_P[0].Data = targetProcNo_P;
                        setCPPacket.objProdNo_C[0].Data = targetProcNo_C;
                        setCPPacket.objTestType[0].Data = targetTestType;
                        setCPPacket.objTestCode[0].Data = targetTestCode;
                        setCPPacket.objVersion[0].Data = targetVersion;
                        setCPPacket.objProdCode[0].Data = targetProdCode;
                        setCPPacket.uiTestListNo = (uint)targetTestListNo;

                        string strSetTestListCntID = targetTestListID;

                        //FileProcess
                        int iSize = File.ReadAllBytes(strFilePos).Length;
                        byte[] ucSendByteInfo = null;

                        if (iSize > SystemXNetSerialization.MAX_PACKET_SIZE)
                        {
                            List<byte[]> getStreamList = XCommons.ObjectToByteStreamList(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.RAW_SIZE), strFilePos, setCPPacket, 0, strSetTestListCntID);

                            if (getStreamList.Count() > 0)
                            {
                                DateTime dtSendTime = DateTime.Now;
                                for (int i = 0; i < getStreamList.Count(); i++)
                                {
                                    if (FlowStreamControl.InsertSendQueue(dtSendTime, getStreamList.ElementAt(i), null, false, true, true) == PacketFlowControl.CommonErrCode)
                                        throw new Exception();
                                }
                            }
                        }
                        else
                        {
                            ucSendByteInfo = XCommons.ObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.FILE_TRANSFER), strFilePos, setCPPacket, 0, 1, true, 1, strSetTestListCntID);

                            if (FlowStreamControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null) == PacketFlowControl.CommonErrCode)
                                throw new Exception();
                        }

                        await WaitTaskJoin(waitStreamParam, FlowStreamControl, PacketFlowControl.TransferResultToken, false).ConfigureAwait(false);
                    }
                    catch (Exception ex)
                    {
                        MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file read and queue control insert fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.CPLogFileTransfer]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                        sendrecvResult = eFileSendRecvResult.FileProcFailed;
                    }
                }
            }
            finally
            {
                FlowStreamControl.STM.ClearLabel(PacketFlowControl.TransferResultToken);
            }

            if (sendrecvResult == eFileSendRecvResult.None)
            {
                if (QueryResult.bFileRecvResult == false)
                    sendrecvResult = eFileSendRecvResult.FileProcFailed;
                else
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;
            }

            FILE_FAILED_BACKUP:

            return sendrecvResult;
        }

        public eFileSendRecvResult SendCustomFile(string strFilePos, bool bResultWait = false, ushort usPalletIndex = 0)
        {
            if (thisConnInfo.ConnectStreamState == false)
                return eFileSendRecvResult.StreamSocketNoConnect;
            if (thisConnInfo.InitialInfoState == false)
                return eFileSendRecvResult.ConnectInitializeFail;
            if (LoadInfo.SIMPLE_LOOKUP_OPTION == true)
                return eFileSendRecvResult.ConnectInitializeFail;

            eFileSendRecvResult sendrecvResult = eFileSendRecvResult.None;

            try
            {
                thisConnInfo.OnStreamTime();

                //File Access Check
                FileStream fs = null;
                try
                {
                    Thread.Sleep(FILE_ACCESS_WAITTIME);

                    fs = new FileStream(strFilePos, FileMode.Open, FileAccess.Read);

                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }
                }
                catch (Exception ex)
                {
                    if (fs != null)
                    {
                        fs.Close();
                        fs = null;
                    }

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file access check fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.SendCustomFile]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    sendrecvResult = eFileSendRecvResult.FileAccessError;
                }
                finally
                {
                    if (sendrecvResult == eFileSendRecvResult.None)
                    {
                        try
                        {
                            //FileProcess
                            int iSize = File.ReadAllBytes(strFilePos).Length;
                            byte[] ucSendByteInfo = null;

                            if (bResultWait)
                                FlowStreamControl.STM.GetLabel(PacketFlowControl.TransferResultToken);

                            if (iSize > SystemXNetSerialization.MAX_PACKET_SIZE)
                            {
                                List<byte[]> getStreamList = XCommons.ObjectToByteStreamList(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.RAW_SIZE), strFilePos);

                                if (getStreamList.Count() > 0)
                                {
                                    DateTime dtSendTime = DateTime.Now;
                                    for (int i = 0; i < getStreamList.Count(); i++)
                                    {
                                        if (FlowStreamControl.InsertSendQueue(dtSendTime, getStreamList.ElementAt(i), null, false, true, true) == PacketFlowControl.CommonErrCode)
                                            throw new Exception();
                                    }
                                }
                            }
                            else
                            {
                                ucSendByteInfo = XCommons.ObjectToByteStream(new BASE_PROTOCOL(BASE_PROTOCOL.PROTOCOL_CODE.FILE_TRANSFER), strFilePos);

                                if (FlowStreamControl.InsertSendQueue(DateTime.Now, ucSendByteInfo, null) == PacketFlowControl.CommonErrCode)
                                    throw new Exception();
                            }

                            if (bResultWait)
                                WaitThreadJoin(waitStreamParam, FlowStreamControl, PacketFlowControl.TransferResultToken, false);
                        }
                        catch (Exception ex)
                        {
                            MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"Send file read and queue control insert fail." + strFilePos + " [SystemX.Net.XAdaptor.PC : XPCAdaptor.SendCustomFile]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                            sendrecvResult = eFileSendRecvResult.FileProcFailed;
                        }
                    }
                }
            }
            finally
            {
                if (bResultWait)
                    FlowStreamControl.STM.ClearLabel(PacketFlowControl.TransferResultToken);
            }

            if (bResultWait)
            {
                if (QueryResult.bFileRecvResult == false)
                    sendrecvResult = eFileSendRecvResult.FileProcFailed;
                else
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;
            }
            else
            {
                if (sendrecvResult == eFileSendRecvResult.None)
                    sendrecvResult = eFileSendRecvResult.FileProcSuccess;
            }

            FILE_FAILED_BACKUP:

            //Failed File Backup Process
            if (sendrecvResult != eFileSendRecvResult.FileProcSuccess)
            {

            }

            return sendrecvResult;
        }

        public eSetConfigFileResult SetConfigureFile(string strFilePos)
        {
            if (strFilePos.Length <= 0)
            {
                if (strSetAdaptorConfigFilePos.Length <= 0)
                    strFilePos = Directory.GetCurrentDirectory() + "\\Configure\\" + "ClientInformation.xml";
                else
                    strFilePos = strSetAdaptorConfigFilePos;
            }

            if (File.Exists(strFilePos))
            {
                strSetAdaptorConfigFilePos = strFilePos;

                if (CheckConfigFileBuildEndPoint())
                {
                    return eSetConfigFileResult.SetConfigSuccess;
                }
                else
                    return eSetConfigFileResult.SetConfigFail;
            }
            else
                return eSetConfigFileResult.SetConfigFail;
        }
    }
}
