using DevExpress.Utils;
using DevExpress.XtraGrid.Views.Grid;
using DevExpress.XtraGrid.Views.Grid.ViewInfo;
using DevExpress.XtraVerticalGrid;
using DevExpress.XtraVerticalGrid.Rows;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using SystemX.Net.Platform.Common.ExtensionMethods;
using SystemX.Product.ALIS.Interface;
using SystemX.Product.ALIS.UI.Subs;
using SystemX.Product.TRA.DataManager;

using static SystemX.Product.CP.TRA.Commons;
using static SystemX.Product.TRA.DataManager.DMTestHistory;
using static SystemX.Product.TRA.DataManager.DMTestSummary;

namespace SystemX.Product.TRA.UIControl
{
    public partial class UcTRASummaryTestResult : UcTRABaseView
    {
        public enum eColDataTable
        {
            StepNo,
            Variant,
            Gate,
            MO,
            Function,
            Min,
            Average,
            Max,
            Dimension,
            Total,
            OK,
            NG, //NOK,
            Duration
        }

        DMTestSummary DataManager { get; set; }
        SelectedDataCollection SelectedData { get; set; }
        DataTable DTLastestTestlistSrc { get; set; } = null;
        DataTable DTTestLogList { get; set; } = null;
        DataTable DTTestSummary { get; set; } = null;

        WaitProgressForm SplashFormWaiting = null;

        string TextShowTL { get; } = "Display the Testlist";
        string TextShowLOG { get; } = "Display the Test Result";

        delegate void evtDBQueryFinished();
        event evtDBQueryFinished evtDBFin;
        
        public delegate void evtStepTrendViewHandler(TestTrendDataCollection data);

        public event evtStepTrendViewHandler OnStepSelect;

        private string GridViewGetActiveFilterText;

        bool bOptionNewStepVersionBase { get; set; }

        IDataBaseController DBController;

        eSelectDataView CurrentSelectView;

        public UcTRASummaryTestResult()
        {
            ContentsType = eContents.TestSumamry;

            InitializeComponent();
        }

        public void SetSQLConnection(eSelectDataView SelectView, IDataBaseController getDBController)
        {
            CurrentSelectView = SelectView;

            DBController = getDBController;

            DataManager = new DMTestSummary(SelectView, DBController);
        }

        public void ViewData(SelectedDataCollection data)
        {
            if (data == null)
                return;

            TestHistorySearchOption Option = new TestHistorySearchOption();
            DMTestHistory LogListMgr = new DMTestHistory(CurrentSelectView, DBController);

            bOptionNewStepVersionBase = true;

            ShowProperties(data);

            SelectedData = data;

            DTTestLogList = LogListMgr.SearchTestHistory(data, Option);

            DTLastestTestlistSrc = DataManager.SearchTestlist(data);
            DTTestSummary = GetSummaryData(data, DTTestLogList);
             
            ShowDetailData();            
        }

        public void ViewData(SelectedDataCollection data, DataTable DataList)
        {
            if (data == null)
                return;

            /*
            FrmOptionSummary optionFrm = new FrmOptionSummary();

            optionFrm.ShowDialog();

            if (optionFrm.DialogResult != DialogResult.OK)
                return;
            
            bOptionNewStepVersionBase = optionFrm.OptaionA ? true : optionFrm.OptaionB ? false : true;
            */

            //TODO : TL Version Find
            bOptionNewStepVersionBase = false;

            SplashFormWaiting = new WaitProgressForm();
            SplashFormWaiting.Parent = this.Parent.Parent;
            SplashFormWaiting.ShowOnTopMode = DevExpress.XtraWaitForm.ShowFormOnTopMode.AboveParent;
            SplashFormWaiting.TopLevel = true;
            SplashFormWaiting.setDescription("Querying ...");
            SplashFormWaiting.Location = new Point(this.Width / 2, this.Height / 2);
            SplashFormWaiting.Show();
            SplashFormWaiting.BringToFront();

            evtDBFin += CloseWaitingForm;

            Thread.Sleep(100);

            try
            {
                ShowProperties(data);

                SelectedData = data;
                DTTestLogList = DataList;

                int nGetStepVersion = int.MinValue;

                //Check Step Version
                foreach (DataRow dr in DataList.Rows)
                {
                    string strGetStepVersion = dr[eColList.StepVersion.ToString()].ToString();
                    int nCurStepVersion = int.MinValue;

                    if (int.TryParse(strGetStepVersion, out nCurStepVersion) == false)
                    {
                        bOptionNewStepVersionBase = true;

                        nGetStepVersion = int.MinValue;

                        break;
                    }
                    else
                    {
                        if (nGetStepVersion == int.MinValue)
                            nGetStepVersion = nCurStepVersion;
                        else if (nGetStepVersion != nCurStepVersion)
                        {
                            bOptionNewStepVersionBase = true;

                            nGetStepVersion = int.MinValue;

                            break;
                        }
                    }
                }


                DTLastestTestlistSrc = DataManager.SearchTestlist(data, nGetStepVersion, bOptionNewStepVersionBase);
                DTTestSummary = GetSummaryData(data, DataList);

                ShowDetailData();                     
            }
            catch (Exception ex)
            {
                MessageBox.Show($"Searching Failure - {ex.Message}", "Test Trend - Error");
            }            
        }

        void CloseWaitingForm()
        {
            this.Do(() => SplashFormWaiting.Close());
        }

        DataTable GetSummaryData(SelectedDataCollection data, DataTable DataList)
        {
            DataTable dtSummary = new DataTable();
            List<Tuple<ulong, ulong>> vnpAccKeysPre = (from drTest in DataList.AsEnumerable()
                                                    where drTest[eColList.ParentNo.ToString()].ToString() != "-"
                                                    let npValue = new Tuple<ulong, ulong>(Convert.ToUInt64(drTest[eColList.AccessStart.ToString()]), Convert.ToUInt64(drTest[eColList.AccessEnd.ToString()]))
                                                    select npValue).OrderBy(x => x.Item1).ToList();

            /*
            List<int> vnpHistStepVersion = (from drTest in DataList.AsEnumerable()
                                                       where drTest[eColList.ParentNo.ToString()].ToString() != "-"
                                                       let npValue = Convert.ToInt32(drTest[eColList.StepVersion.ToString()])
                                                       select npValue).ToList();
            */

            List<Int64> vnpHistSummaryNo = (from drTest in DataList.AsEnumerable()
                                                       where drTest[eColList.ParentNo.ToString()].ToString() != "-"
                                                       let npValue = Convert.ToInt64(drTest[eColList.No.ToString()])
                                                       select npValue).ToList();

            /*
            List<Tuple<ulong, ulong>> vnpAccKeysPost = new List<Tuple<ulong, ulong>>();            
            Tuple<ulong, ulong> unpItem = null;

            vnpAccKeysPre.RemoveAll(x => x.Item1 == 0 && x.Item2 == 0);

            foreach (Tuple<ulong, ulong> preVal in vnpAccKeysPre)
            {
                if(unpItem == null)
                    unpItem = new Tuple<ulong, ulong>(preVal.Item1, preVal.Item2);
                else
                {
                    if(preVal.Item1 - unpItem.Item2 == 1)
                        unpItem = new Tuple<ulong, ulong>(unpItem.Item1, preVal.Item2);
                    else
                    {
                        vnpAccKeysPost.Add(unpItem);

                        unpItem = new Tuple<ulong, ulong>(preVal.Item1, preVal.Item2);
                    }
                }
            }

            if((vnpAccKeysPost.Count == 0 || (vnpAccKeysPost.Last().Item1 != unpItem.Item1)) && unpItem != null)
                vnpAccKeysPost.Add(unpItem);           
            */

            dtSummary = DataManager.SearchTestSummary(data.StartTime, /* vnpAccKeysPost */ vnpAccKeysPre, vnpHistSummaryNo);
            
            evtDBFin();

            return dtSummary;
        }

        DataTable CombineLogForm()
        {
            //if (DTTestLogSrc == null || DTTestlistSrc == null)
            //    return null;

            DataTable dtFinal = new DataTable();

            foreach(string strCol in Enum.GetNames(typeof(eColDataTable)))
            {
                Type typCol = typeof(string);

                if (strCol == eColDataTable.StepNo.ToString())
                    typCol = typeof(int);
                else if (strCol == eColDataTable.Duration.ToString() 
                        || strCol == eColDataTable.Total.ToString()
                        || strCol == eColDataTable.OK.ToString()
                        || strCol == eColDataTable.NG.ToString())
                    typCol = typeof(int);

                dtFinal.Columns.Add(strCol, typCol);
            }

            DataRow drTL = null;
            List<DataRow> vdrTL = null;

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

            foreach (DataRow drLog in DTTestSummary.AsEnumerable())
            {
                //PK 기준 검색
                if (bOptionNewStepVersionBase)
                {
                    drTL = DTLastestTestlistSrc.Rows.Find(drLog[eColTestLog.StepID.ToString()]);

                    if (drTL == null)
                        continue;
                }
                else
                {
                    /*
                    int nAccessPos = int.MaxValue;
                    for (int i = 0; i <= DataManager.nCurrentTLMaxStepVersion; i++)
                    {
                        string strChkResult = drLog["SV" + i.ToString()].ToString();

                        if (strChkResult.CompareTo("O") == 0)
                        {
                            nAccessPos = i;
                            break;
                        }
                    }

                    if (nAccessPos == int.MaxValue)
                        continue;
                    */

                    //drTL = DataManager[nAccessPos].Rows.Find(drLog[eColTestLog.StepID.ToString()]);
                    drTL = DataManager.dtHistVersionTL.Rows.Find(drLog[eColTestLog.StepID.ToString()]);

                    if (drTL == null)
                        continue;

                    /*vdrTL = DTLastestTestlistSrc.AsEnumerable().Where(x => Convert.ToInt32(x[eColTestlist.StepID.ToString()]) == Convert.ToInt32(drLog[eColTestSummary.StepID.ToString()])).ToList();

                    if (vdrTL.IsNullOrEmpty())
                        continue;

                    drTL = GetProperTestStepVersion(vdrTL, drLog);*/
                }

                DataRow drDisp = dtFinal.NewRow();
                
                drDisp[eColDataTable.StepNo.ToString()] = Convert.ToInt32(Convert.ToInt32(drLog[eColTestSummary.StepID.ToString()]));
                drDisp[eColDataTable.Variant.ToString()] = drTL[eColTestlist.Variant.ToString()].ToString();
                drDisp[eColDataTable.Gate.ToString()] = drTL[eColTestlist.Gate.ToString()].ToString();
                drDisp[eColDataTable.MO.ToString()] = drTL[eColTestlist.StepDesc.ToString()].ToString();
                drDisp[eColDataTable.Function.ToString()] = drTL[eColTestlist.UseFunction.ToString()].ToString();

                bool bIsGlobal = (Convert.ToInt32(drTL[eColTestlist.IsGlobal.ToString()])) > 0 ? true : false;

                drDisp[eColDataTable.Min.ToString()] = bIsGlobal ? "Global Var" : drTL[eColTestlist.SpecMin.ToString()].ToString();
                drDisp[eColDataTable.Max.ToString()] = bIsGlobal ? "Global Var" : drTL[eColTestlist.SpecMax.ToString()].ToString();

                var strMeasVal = drLog[eColTestSummary.Average.ToString()];
                int nOK = Convert.ToInt32(drLog[eColTestSummary.OK.ToString()]);
                int nNOK = Convert.ToInt32(drLog[eColTestSummary.NG.ToString()]);

                drDisp[eColDataTable.Average.ToString()] = strMeasVal == null ? string.Empty : (nOK + nNOK) == 0 ? string.Empty : strMeasVal.ToString();

                drDisp[eColDataTable.Dimension.ToString()] = drTL[eColTestlist.Dim.ToString()].ToString();

                drDisp[eColDataTable.Total.ToString()] = Convert.ToInt32(drLog[eColTestSummary.Total.ToString()]);
                drDisp[eColDataTable.OK.ToString()] = nOK;
                drDisp[eColDataTable.NG.ToString()] = nNOK;
                //drDisp[eColDataTable.Duration.ToString()] = 0; //Convert.ToInt32(Convert.ToInt32(drLog[eColTestLog.Duration.ToString()]));

                dtFinal.Rows.Add(drDisp);
            }

            long lTime = stChkTime.ElapsedMilliseconds;

            return dtFinal;
        }

        DataRow GetProperTestStepVersion(List<DataRow> vTestStepDef, DataRow drLog)
        {
            return vTestStepDef.FirstOrDefault();
        }

        void ShowDetailData()
        {
            DataTable dtResult = CombineLogForm();

            GridViewGetActiveFilterText = gridViewMain.ActiveFilterString;

            gridControlMain.BeginInit();

            gridControlMain.DataSource = dtResult;

            gridControlMain.Update();
            gridControlMain.RefreshDataSource();
            gridControlMain.ForceInitialize();
            gridViewMain.PopulateColumns(dtResult);
            gridControlMain.EndInit();

            gridViewMain.ActiveFilterString = GridViewGetActiveFilterText;
        }
        
        void ShowProperties(SelectedDataCollection data)
        {
            vGridControlInfo.Rows.Clear();

            foreach (PropertyInfo propInf in data.GetType().GetProperties())
            {
                EditorRow dtRow = new EditorRow();

                dtRow.Properties.Caption = propInf.Name;

                if (propInf.Name == "TestRequestID")
                    dtRow.Properties.Value = ((string[])propInf.GetValue(data, null))[0];
                else
                    dtRow.Properties.Value = propInf.GetValue(data, null)?.ToString();

                vGridControlInfo.Rows.Add(dtRow);
            }

            OnSizeChanged(vGridControlInfo);
           
        }

        void OnSizeChanged(VGridControl grid)
        {
            int width = grid.ClientSize.Width / (grid.RecordCount + 1);
            grid.RecordWidth = width;
            grid.RowHeaderWidth = width;
        }

        private void UcTRADetailTestResult_Load(object sender, System.EventArgs e)
        {
        }

        private void gridViewMain_DoubleClick(object sender, EventArgs e)
        {
            DXMouseEventArgs ea = e as DXMouseEventArgs;
            GridView view = sender as GridView;
            GridHitInfo info = view.CalcHitInfo(ea.Location);

            if (info.InRow || info.InRowCell)
            {
                int nRow = int.MinValue;
                nRow = info.RowHandle;

                if (nRow < 0)
                    return;

                var dvRow = view.GetRow(nRow);
                DataRow dtRow = (dvRow as DataRowView).Row;
                TestTrendDataCollection dataSend = new TestTrendDataCollection();

                dataSend.DTTestlistSrc = DTLastestTestlistSrc;
                dataSend.DTTestLogList = DTTestLogList;
                dataSend.SelectedData = SelectedData;
                dataSend.StepNo = dtRow[eColDataTable.StepNo.ToString()].ToString();
                dataSend.Variant = dtRow[eColDataTable.Variant.ToString()].ToString();
                dataSend.Gate = dtRow[eColDataTable.Gate.ToString()].ToString();
                dataSend.MO = dtRow[eColDataTable.MO.ToString()].ToString();
                dataSend.Function = dtRow[eColDataTable.Function.ToString()].ToString();
                dataSend.Total = dtRow[eColDataTable.Total.ToString()].ToString();
                dataSend.OK = dtRow[eColDataTable.OK.ToString()].ToString();
                dataSend.NG = dtRow[eColDataTable.NG.ToString()].ToString();

                OnStepSelect(dataSend);
            }
        }
    }
}
