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.Threading.Tasks;

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 SystemX.Common.Protocol.SIA;

using DevExpress.Utils.Extensions;

using static SystemX.Net.Platform.Common.Util.LogMessage;
using static SystemX.Net.DB.LogProcess.XLogDBConnManager;
using SystemX.Net.Platform.SystemX.Common;

namespace SystemX.Net.MiddlewareUI
{
    public partial class MainForm : DevExpress.XtraBars.FluentDesignSystem.FluentDesignForm
    {
        private async void WatchRecvCommandQueue()
        {
            await Task.Delay(250);

            while (!m_bTaskCommandBlock)
            {
                try
                {
                    CT.ThrowIfCancellationRequested();
                }
                catch (OperationCanceledException CancelEx)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Work Canceled. [SystemX.Net.MiddlewareUI : MainForm.WatchRecvCommndQueue]\r\n" + CancelEx.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                    break;
                }
                //
                try
                {
                    if (bTaskCommandWaitLock == false)
                        QueryRecvCommandQueue();
                }
                catch (Exception e)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"General Queue Process failed.[1] [SystemX.Net.MiddlewareUI : MainForm.WatchRecvCommndQueue]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }

                await Task.Delay(500);
            }
        }

        private bool LogMemoryPushProcess(int nPos, int nStPos)
        {
            int nSetSize = int.MaxValue;
            byte[] ucSetLogArray = null;

            bool bProcResult = false;

            using (LogSharedMemory memLog = new LogSharedMemory(ParamterMapLog))
            {
                if (memLog.CheckFile(nPos))
                {
                    LogMappedPacket LogMapFile = new LogMappedPacket();
                    nSetSize = Marshal.SizeOf(LogMapFile);
                    ucSetLogArray = new byte[nSetSize];
                    LogMapFile = (LogMappedPacket)SystemXNetSerialization.RawDeSerialize(ucSetLogArray, LogMapFile.GetType());

                    bool bFindLogResult = false;

                    LogMapFile = memLog.Get(nPos, nStPos, out bFindLogResult, nSetSize).Value;

                    if (bFindLogResult == false)
                        return false;

                    if (LogMapFile.bLogFileReadComplete == false)
                    {
                        LogMapFile.bLogFileReadComplete = true;

                        memLog.Set(nPos, LogMapFile);

                        StringBuilder sb = new StringBuilder();
                        sb.Append("[" + (++nEnqueueCount).ToString() + "][Enqueue]");
                        sb.Append("[");
                        sb.Append(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss"));
                        sb.Append("], ");
                        sb.Append("Type [" + LogMapFile.objLogType[0].Data.ToString() + "], ");
                        sb.Append("S Port [" + LogMapFile.nStreamPort.ToString() + "], ");
                        sb.Append("C Port [" + LogMapFile.nCommandPort.ToString() + "], ");
                        sb.Append("Size [" + LogMapFile.nLogDataSize.ToString() + "], ");
                        sb.Append("Number [" + LogMapFile.nNumber.ToString() + "], ");
                        sb.Append("Host [" + LogMapFile.objHost[0].Data + "], ");
                        sb.Append("Section [" + LogMapFile.objSection[0].Data + "], ");
                        sb.Append("St Name [" + LogMapFile.objStationName[0].Data + "], ");
                        sb.Append("St ID [" + LogMapFile.nStationID.ToString() + "], ");
                        sb.Append("File Name [" + LogMapFile.objOptionFileName[0].Data + "], ");
                        sb.Append("File Extension [" + LogMapFile.objOptionFileExtension[0].Data + "] ");

                        /*
                        sb.Append("TL ID[" + LogMapFile.objResultTestListCntID[0].Data + "], ");
                        sb.Append("V[" + LogMapFile.objProdPNo[0].Data + "], ");
                        sb.Append("PN[" + LogMapFile.objProdCNo[0].Data + "], ");
                        sb.Append("TT[" + LogMapFile.objTestType[0].Data + "], ");
                        sb.Append("TC[" + LogMapFile.objTestCode[0].Data + "], ");
                        sb.Append("Ver[" + LogMapFile.objVersion[0].Data + "], ");
                        sb.Append("PC[" + LogMapFile.objProdCode[0].Data + "], ");
                        sb.Append("DB V No[" + LogMapFile.nTestListVariantNo.ToString() + "] ");
                        */

                        sb.AppendLine();

                        if (nEnqueueCount >= Int64.MaxValue)
                            nEnqueueCount = 0;

                        LogDataRecvText.Enqueue(sb);

                        LogDataQueue[nPos].Enqueue(LogMapFile);
                      
                        bProcResult = true;
                    }
                }
            }

            return bProcResult;
        }

        private bool QueryRecvCommandQueue()
        {
            bool bState = true;

            string strProcessDebugInfo = string.Empty;

            long l1 = long.MinValue;
            long l2 = long.MinValue;

            try
            {
                bTaskCommandWaitLock = true;

                Stopwatch stProcessTimeChk = new Stopwatch();
                stProcessTimeChk.Start();

                using (InfoLogSharedMemory memInfoLog = new InfoLogSharedMemory(ParamterMapInfoLog))
                {
                    InfoLogMappedPacket InfoLogMapFile = new InfoLogMappedPacket();
                    int nSetSize = Marshal.SizeOf(InfoLogMapFile);
                    byte[] ucSetLogArray = new byte[nSetSize];
                    InfoLogMapFile = (InfoLogMappedPacket)SystemXNetSerialization.RawDeSerialize(ucSetLogArray, InfoLogMapFile.GetType());

                    if (memInfoLog.CheckFile())
                    {
                        bool bFindInfoLogResult = false;

                        //로그 처리가 필요한 위치 조회
                        bool[] bGetStationReadyLog = memInfoLog.Get(out bFindInfoLogResult, nSetSize);

                        if (bFindInfoLogResult == false)
                            return bState;

                        //Array.Copy(bGetStationReadyLog, 0, InfoLogMapFile.bLogDataReady, 0, SharedMemory.nMaxInfoFullAccessSize);

                        Array.Clear(bCompareLogReadyState, 0, SharedMemory.nMaxInfoFullAccessSize);
                        for (int i = 0; i < SharedMemory.nMaxInfoFullAccessSize; i++)
                        {
                            if (bGetStationReadyLog[i] != bBeforeLogReadyState[i])
                                bCompareLogReadyState[i] = true;
                        }

                        //존재할 경우
                        if (bCompareLogReadyState.Any(x => x == true))
                        {
                            //존재하는 개수 파악
                            bool[] arrCheckNum = Array.FindAll(bCompareLogReadyState, x => x == true);

                            //개수 확인
                            int nFindCount = arrCheckNum.Count();

                            //개수 만큼 Index 확인
                            for (int i = 0; i < nFindCount; i++)
                            {
                                Stopwatch stItemTimeChk = new Stopwatch();
                                stItemTimeChk.Start();

                                int nIdx = Array.FindIndex(bCompareLogReadyState, x => x == true);

                                //Index 포트 변환 및 Station(최대 8) 확인
                                int nPos = (nIdx / SharedMemory.nMaxStationSize) + PORT_DISTRIBUTION_NUM;

                                int nAccessPart = nIdx / SharedMemory.nMaxStationSize;
                                int nSubPos = nIdx % SharedMemory.nMaxStationSize;

                                if (bCompareLogReadyState[nIdx])
                                {
                                    LogMemoryPushProcess(nPos, nSubPos);

                                    bCompareLogReadyState[nIdx] = false;
                                }

                                l2 = stItemTimeChk.ElapsedMilliseconds;
                            }

                            /*for (int i = PORT_DISTRIBUTION_NUM; i < ALL_MANAGE_NUM && !m_bTaskStreamBlock; i++)
                            {
                                for (int j = (i - PORT_DISTRIBUTION_NUM) * SharedMemory.nMaxStationSize;
                                    j < ((i - PORT_DISTRIBUTION_NUM) * SharedMemory.nMaxStationSize) + SharedMemory.nMaxStationSize; j++)
                                {
                                    if (bGetStationReadyLog[j])
                                    {
                                        LogMemoryProcess(i, j);

                                        bGetStationReadyLog[j] = false;
                                    }
                                }

                                Thread.Sleep(10);
                            }*/

                            //memInfoLog.Set(bGetStationReadyLog);
                            Array.Copy(bGetStationReadyLog, 0, bBeforeLogReadyState, 0, SharedMemory.nMaxInfoFullAccessSize);
                        }
                    }

                }

                l1 = stProcessTimeChk.ElapsedMilliseconds;

                if (l1 != long.MinValue && l2 != long.MinValue)
                {
                    LogDataRecvText.Enqueue(new StringBuilder(">>[Enqueue-Process][" + l1.ToString() + "][Enqueue-Item][" + l2.ToString() + "]\r\n"));
                }
            }
            catch (Exception e)
            {
                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + strProcessDebugInfo + @" Recv queue process fail.[SystemX.Net.MiddlewareUI : MainForm.QueryRecvCommandQueue]\r\n" + e.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);

                bState = false;
            }
            finally
            {
                bTaskCommandWaitLock = false;
            }

            return bState;
        }
    }
}
