using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml.Linq;
using SystemX.Net;
using SystemX.Net.BaseProtocol;
using SystemX.Net.DB;

using CpTesterPlatform.CpLogUtil;

using static SystemX.Net.Platform.Common.Util.LogMessage;
using static SystemX.Net.DB.XDBConnManager;

namespace SystemX.Common.Log.SIA
{
    public class AnalysisLog_SIA : IDisposable
    {
        public bool STATE { set; get; }

        //DataBase
        private XDBConnManager MngDBConn;
        //QueryInfo
        public LogProcessInfo_SIA qiLogProcessInfo;
        //Log Scan Process Task 
        private Task taskScanProcess;

        private bool m_bTaskBlock;
        //
        private Stopwatch stProcessTime;

        private long lLastProcessTime;
        private long lLastItemTime;
        private long lLastProcessNum;

        private CancellationTokenSource cts;

        public int SET_LOG_PROC_POS { set; get; }
        public int SET_LOG_DELETE_MANAGE_POS { set; get; }

        public int SET_LOG_SCAN_SHIFT_TIME { set; get; }
        public int SET_LOG_MANAGE_SCAN_TIME { set; get; }
        //
        private string strLogDataFilePath { set; get; }
        private eLogDataType eGetLogDataType { set; get; }
        private eLogAccessType eGetAccessType { set; get; }
        private CpLogHeader getCpLogHeader;
        //
        public bool[] LOG_DATA_CHECK_STATE { set; get; }

        public long GET_LAST_PROCESS_TIME()
        {
            return lLastProcessTime;
        }
        public long GET_LAST_PROCESS_NUM()
        {
            return lLastProcessNum;
        }
        public long GET_LAST_ITEM_TIME()
        {
            return lLastItemTime;
        }

        ~AnalysisLog_SIA()
        {
            Dispose(false);
        }
        public AnalysisLog_SIA()
        {
            STATE = true;

            //Proc Position
            SET_LOG_PROC_POS = 0;
            SET_LOG_DELETE_MANAGE_POS = 0;

            //1초 마다 미 처리 로그 스캔
            SET_LOG_SCAN_SHIFT_TIME = 500;

            //24시간 마다 삭제 대상 데이터 스캔
            SET_LOG_MANAGE_SCAN_TIME = 86400000;

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

            lLastProcessTime = 0;
            lLastItemTime = 0;

            lLastProcessNum = 0;

            MessageOutput.PrintLogLevel = LogMessageLevel.INFO;

            string strExcutePos = Environment.CurrentDirectory;
            string strDBInfoPos = strExcutePos + @"\Configure\DBConnInfo.xml";
            string strLogProcessInfoPos = strExcutePos + @"\Configure\LogProcessInfo.xml";

            qiLogProcessInfo = new LogProcessInfo_SIA(strLogProcessInfoPos);
            if (qiLogProcessInfo.Load())
            {
                LOG_DATA_CHECK_STATE = new bool[qiLogProcessInfo.GeManageInfo().Count()];
                for (int i = 0; i < qiLogProcessInfo.GeManageInfo().Count(); i++)
                    LOG_DATA_CHECK_STATE[i] = true;

                MngDBConn = new XDBConnManager();
                MngDBConn.ConfigPath = strDBInfoPos;

                if (MngDBConn.OpenConnection())
                {
                    taskScanProcess = null;
                    m_bTaskBlock = false;

                    cts = new CancellationTokenSource();
                    taskScanProcess = new Task(new Action<object>(WatchResultTable), cts.Token);
                    taskScanProcess.Start();

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Success to connect to DB. [SystemX.Common.Protocol.Log.LSU_Trimming_4Th : AnalysisLog_.AnalysisLog_]", ConsoleColor.White, LogMessageLevel.DEBUG);
                }
                else
                {
                    STATE = false;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Failed to connect to DB. [SystemX.Common.Protocol.Log.LSU_Trimming_4Th : AnalysisLog_.AnalysisLog_]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
            }
            else
            {
                STATE = false;

                MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @" Read to configure failed. [SystemX.Common.Protocol.Log.LSU_Trimming_4Th : AnalysisLog_.AnalysisLog_]", ConsoleColor.Yellow, LogMessageLevel.DEBUG);
            }
        }
        public void Dispose()
        {
            Dispose(true);
        }
        protected virtual void Dispose(bool bDisposing)
        {
            if (bDisposing)
            {

            }

            if (taskScanProcess != null)
            {
                cts.Cancel();

                taskScanProcess.Wait();

                m_bTaskBlock = true;
            }

            // do releasing unmanaged resource (종결자가 없는 객체의 자원 해제)
            // i.e. close file handle of operating systems

            // suppress calling of Finalizer
            GC.SuppressFinalize(this);
        }
        private DataSet QueryProcess(string strGetQuery, ref bool bResult)//, out byte[] ucQueryByteArray)
        {
            bResult = false;

            SqlDataReader xSqlReader = null;

            DataSet ds = new DataSet();
            DataTable dt = new DataTable();

            int iFieldCnt = 0;
            int iRecordsAffectedCnt = 0;
            bool bHasRow = false;

            //ucQueryByteArray = null;

            try
            {
                try
                {
                    xSqlReader = MngDBConn.QueryDatabase(eConnCategory.Main, strGetQuery);

                    if (xSqlReader != null)
                    {
                        iFieldCnt = xSqlReader.FieldCount;
                        iRecordsAffectedCnt = xSqlReader.RecordsAffected;
                        bHasRow = xSqlReader.HasRows;

                        dt.Load(xSqlReader);
                        ds.Tables.Add(dt);
                    }
                }
                catch (Exception ex)
                {
                    xSqlReader = null;

                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"<" + strGetQuery + "> Query process fail![SystemX.Net.Platform.Log : AnalysisLog_.QueryProcess]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }
            }
            finally
            {
                if (xSqlReader != null)
                    xSqlReader.Close();
            }

            if (iFieldCnt > 0 || iRecordsAffectedCnt > 0 || bHasRow == true)
                bResult = true;

            return ds;
        }
        private async void WatchResultTable(object objState)
        {
            CancellationToken token = (CancellationToken)objState;

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

            while (!m_bTaskBlock)
            {
                if (token.IsCancellationRequested)
                    break;

                try
                {
                    if ((stLogManageTimer.ElapsedMilliseconds >= SET_LOG_MANAGE_SCAN_TIME))
                    {
                        if (qiLogProcessInfo.USE_TABLE_DATA_DELETE_MANAGER)
                        {
                            foreach (KeyValuePair<int, Tuple<bool, string, int>> infoM in qiLogProcessInfo.GeManageInfo())
                            {
                                if (infoM.Value.Item1)
                                {
                                    int[] iGetDeleteNo = QueryManageDateTable(infoM.Value.Item2, infoM.Value.Item3.ToString(), token);

                                    if (iGetDeleteNo != null)
                                    {
                                        ManageTableDataDelete(iGetDeleteNo, infoM.Value.Item2, infoM.Value.Item3.ToString(), token);
                                    }

                                    iGetDeleteNo = QueryManageDateTable(infoM.Value.Item2, infoM.Value.Item3.ToString(), token);
                                }
                            }
                        }

                        stLogManageTimer.Restart();
                    }
                }
                catch (Exception ex)
                {
                    MessageOutput.ConsoleWrite(DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss>>") + @"General Queue Process failed.[SystemX.Common.Protocol.Log.LSU_Trimming_4Th : AnalysisLog_SIA.WatchResultTable]\r\n" + ex.Message, ConsoleColor.Yellow, LogMessageLevel.DEBUG);
                }

                await Task.Delay(1);
            }
        }
        public int[] QueryManageDateTable(string strTableName, string strDateDiff, CancellationToken token)
        {
            bool bGetQueryResult = false;

            int[] iQueryNoArr = null;

            DataSet ds = QueryProcess("SELECT TOP(100) * FROM [" + strTableName + "] WHERE No " +
            "IN(SELECT No FROM [" + strTableName + "] WHERE " +
            "CONVERT(VARCHAR(8), UpdateDT, 112) <= CONVERT(VARCHAR(8), GETDATE() - " + strDateDiff + ", 112)) ORDER BY No;", ref bGetQueryResult);

            bool hasRows = XCommons.isHasRow(ds);

            if (hasRows)
            {
                int iRowNum = ds.Tables[0].Rows.Count;

                iQueryNoArr = new int[iRowNum];
                Array.Clear(iQueryNoArr, 0, iQueryNoArr.Length);

                for (int i = 0; i < iRowNum; i++)
                {
                    if (token.IsCancellationRequested)
                        return null;

                    var getValue = ds.Tables[0].Rows[i]["No"];

                    iQueryNoArr[i] = int.Parse(getValue.ToString());
                }
            }

            stProcessTime.Restart();

            return iQueryNoArr;
        }
        public bool ManageTableDataDelete(int[] iGetNoArray, string strTableName, string strDateDiff, CancellationToken token)
        {
            bool bGetQueryResult = false;

            bool bFindItem = false;
            long lDataNum = 0;

            foreach (int iGetNo in iGetNoArray)
            {
                bFindItem = true;

                lDataNum = iGetNoArray.Count();

                if (token.IsCancellationRequested)
                    break;

                /*
                QueryProcess("DELETE [" + strTableName + "] WHERE " +
                "CONVERT(VARCHAR(8), UpdateDT, 112) <= CONVERT(VARCHAR(8), GETDATE() - " + strDateDiff + ", 112);", ref bGetQueryResult);
                */

                QueryProcess("DELETE [" + strTableName + "] WHERE No = " + iGetNo + ";", ref bGetQueryResult);
            }

            if (bFindItem)
            {
                lLastProcessTime = stProcessTime.ElapsedMilliseconds;
                lLastProcessNum = lDataNum;
            }

            return true;
        }
    }
}
