using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Data.SqlClient;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Xml.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using static System.Windows.Forms.ComboBox;

using SystemX.Product.ALIS.Interface;

using CpApplication;
using CpApplication.Manager;
using CpCommon;
using CpTesterPlatform.CpLogUtil;
using static PsCommon.PsCommon;

using PsKGaudi;
using PsKGaudi.Parser.PsCCSArea;
using PsKGaudi.Parser.PsCCSSTDFn;
using PsKGaudi.Parser.MacroModuleSkel;
using PsKGaudi.Parser.PsCCSSTDFn.Parameters;
using static PsKGaudi.Parser.PsCCS;

using static CpCommon.ExceptionHandler;
using SystemX.Common;

namespace SystemX.Product.ALIS.UI.View.InfoList
{
    public partial class TestListInfoReleaseEdit : Form
    {
        [Flags]
        private enum eDataFindMode
        {
            None = 0x00,
            P_ProdNo = 0x01,
            TestType = 0x02,
            Version = 0x03,
            FileName = 0x04
        }

        public eSelectMode CurrentWizardMode { internal set; get; }

        private CReleaseInformation ctrlTestListRelInformation;

        private IDataController ctrlDB;

        private static object objInfoControlNextLock = new object();

        private string strGetModifyProdCInfo;
        private string strGetModifyTestCodeInfo;
        private string strGetModifyTestListInfo;

        public enum eSelectMode
        {
            Insert = 0,
            Modify
        }

        private string strTitle = "PROD TestList-Release";
        private string strWizardControl = "PROD TestList-Release";
        private string strWelcomeWizard = "Welcome to the PROD TestList-Release wizard!";
        private string strWizardPage = "PROD TestList Release Information";

        private bool TestCodeCheckResult { set; get; } = false;
        private bool TestListCheckResult { set; get; } = false;

        public void WizardCancelEvent(object sender, EventArgs e)
        {
            if (((bool)sender) == false)
                this.DialogResult = DialogResult.Cancel;
        }

        private bool CheckTestCodeInfo(DataTable dt)
        {
            if (XCommons.isHasRow(dt) == false)
            {
                textBoxTextCodeInput.BackColor = Color.Red;

                return false;
            }

            DataSet ds = new DataSet();
            ds.Tables.Add(dt);

            textBoxDispTestCodeNo.Text = dt.Rows[0][0].ToString();
            textBoxDispTestCode.Text = dt.Rows[0][1].ToString();
            textBoxDispGate1.Text = dt.Rows[0][2].ToString();
            textBoxDispGate2.Text = dt.Rows[0][3].ToString();
            textBoxDispComment.Text = dt.Rows[0][4].ToString();

            textBoxTextCodeInput.Text = dt.Rows[0][1].ToString();

            TestCodeCheckResult = true;

            textBoxTextCodeInput.BackColor = Color.LimeGreen;

            return true;
        }

        private void GetTestCodeList()
        {
            SqlDataReader reader;

            ctrlDB.GetConnSqlCmd().CommandText = "SELECT * FROM STAT_TestCode WITH(NOLOCK) ORDER BY No ASC;";

            reader = ctrlDB.GetConnSqlCmd().ExecuteReader();
            DataSet ds = new DataSet();
            DataTable dt = new DataTable();
            dt.Load(reader);
            ds.Tables.Add(dt);
            reader.Close();

            comboBoxTestCodeList.Items.Clear();

            if (XCommons.isHasRow(ds))
            {
                comboBoxTestCodeList.Items.Add("Select Test Code ...");
                comboBoxTestCodeList.SelectedIndex = 0;

                for (int i = 0; i < dt.Rows.Count; i++)
                    comboBoxTestCodeList.Items.Add(dt.Rows[i]["TestCode"].ToString());
            }
        }

        private bool CheckTestListInfo(DataTable dt)
        {
            if (XCommons.isHasRow(dt) == false)
            {
                textBoxPProdNoInput.BackColor = Color.Red;
                textBoxDispInTestType.BackColor = Color.Red;
                textBoxDispInVersion.BackColor = Color.Red;
                textBoxDispInProdCode.BackColor = Color.Red;
                textBoxDispInFileName.BackColor = Color.Red;

                textBoxDispInTestType.ReadOnly = false;
                textBoxDispInVersion.ReadOnly = false;
                textBoxDispInProdCode.ReadOnly = false;
                textBoxDispInFileName.ReadOnly = false;

                return false;
            }

            DataSet ds = new DataSet();
            ds.Tables.Add(dt);

            textBoxDispTestListVariantNo.Text = dt.Rows[0][0].ToString();
            textBoxPProdNoInput.Text = dt.Rows[0][1].ToString();
            textBoxDispInTestType.Text = dt.Rows[0][2].ToString();
            textBoxDispInVersion.Text = dt.Rows[0][3].ToString();
            textBoxDispInProdCode.Text = dt.Rows[0][4].ToString();
            textBoxDispInFileName.Text = dt.Rows[0][5].ToString();
            textBoxDispTestListComment.Text = dt.Rows[0][6].ToString();
            textBoxDispTestListDescription.Text = dt.Rows[0][7].ToString();

            textBoxPProdNoInput.Text = dt.Rows[0][1].ToString();

            TestListCheckResult = true;

            textBoxPProdNoInput.BackColor = Color.LimeGreen;
            textBoxDispInTestType.BackColor = Color.LimeGreen;
            textBoxDispInVersion.BackColor = Color.LimeGreen;
            textBoxDispInProdCode.BackColor = Color.LimeGreen;
            textBoxDispInFileName.BackColor = Color.LimeGreen;

            textBoxDispInTestType.ReadOnly = true;
            textBoxDispInVersion.ReadOnly = true;
            textBoxDispInProdCode.ReadOnly = true;
            textBoxDispInFileName.ReadOnly = true;

            return true;
        }

        public TestListInfoReleaseEdit(IDataController ctrlDB, eSelectMode setMode, CReleaseInformation getSelTestListRelInfo)
        {
            InitializeComponent();

            this.Text = strTitle;
            wizardControl.Text = strWizardControl;
            welcomeWizardPage.Text = strWelcomeWizard;
            wizardPage.Text = strWizardPage;
            
            CurrentWizardMode = setMode;
            ctrlTestListRelInformation = getSelTestListRelInfo;

            this.ctrlDB = ctrlDB;

            GetTestCodeList();

            switch (CurrentWizardMode)
            {
                case eSelectMode.Insert:
                    welcomeWizardPage.IntroductionText = "This is the procedure to insert new information into the " + strTitle + " table.";
                    wizardControl.Text = strTitle + " - Insert";
                    this.Text = strTitle + " - Insert";

                    textBoxItem5_Picker.Value = getSelTestListRelInfo.RegDT;
                    textBoxItem6.Text = getSelTestListRelInfo.RegUser;
                    break;
                case eSelectMode.Modify:
                    welcomeWizardPage.IntroductionText = "This is the procedure to modify new information in the " + strTitle + " table.";
                    wizardControl.Text = strTitle + " - Modify";
                    this.Text = strTitle + " - Modify";

                    textBoxItem1.Text = getSelTestListRelInfo.ProdNo_C;

                    DataTable dtTestCode = ctrlDB.GetTable("SELECT * FROM STAT_TestCode WHERE No = " + getSelTestListRelInfo.TestCodeNo + " ORDER BY No ASC;");

                    CheckTestCodeInfo(dtTestCode);

                    DataTable dtTestList = ctrlDB.GetTable($"SELECT X.No, X.ProdNo_P, Y.TestType, Y.Version, Y.ProdCode, Y.FileName, X.Comment, X.Description FROM [PROD_Variant] AS X WITH(NOLOCK) " +
                        $"INNER JOIN [STOR_TestListFile] AS Y WITH(NOLOCK) ON X.TestListFileNo = Y.No " +
                        $"WHERE X.No = " + getSelTestListRelInfo.VariantNo + " ORDER BY No ASC;");

                    CheckTestListInfo(dtTestList);

                    textBoxItem4.Text = getSelTestListRelInfo.Config;
                    textBoxItem5_Picker.Value = getSelTestListRelInfo.RegDT;
                    textBoxItem6.Text = getSelTestListRelInfo.RegUser;
                    textBoxItem7.Text = getSelTestListRelInfo.RegUserComment;

                    strGetModifyProdCInfo = textBoxItem1.Text;
                    strGetModifyTestCodeInfo = textBoxDispTestCodeNo.Text;
                    strGetModifyTestListInfo = textBoxDispTestListVariantNo.Text;
                    break;
            }
        }

        private void wizardControl_NextClick(object sender, DevExpress.XtraWizard.WizardCommandButtonClickEventArgs e)
        {
            if (wizardControl.SelectedPageIndex == 1)
            {
                lock (objInfoControlNextLock)
                {
                    try
                    {
                        string strItemName = "";
                        if (textBoxItem1.Text.Length <= 0) { strItemName = "ProdNo_C"; throw new Exception($"The value cannot be null. [" + strItemName + "]"); }

                        if (TestCodeCheckResult == false) { strItemName = "TestCode No"; throw new Exception($"The value must be select and check. [" + strItemName + "]"); }
                        if (TestListCheckResult == false) { strItemName = "TestList No"; throw new Exception($"The value must be select and check. [" + strItemName + "]"); }

                        if (textBoxItem4.Text.Length <= 0) { strItemName = "Config"; throw new Exception($"The value cannot be null. [" + strItemName + "]"); }

                        string strGetProdC = textBoxItem1.Text;
                        string strGetTestCodeNo = textBoxDispTestCodeNo.Text;

                        string strGetTestCode = textBoxDispTestCode.Text;
                        string strGetTestType = textBoxDispInTestType.Text;
                        string strGetVersion = textBoxDispInVersion.Text;
                        string strGetProdCode = textBoxDispInProdCode.Text;

                        string strGetTestListNo = textBoxDispTestListVariantNo.Text;

                        //"SELECT * FROM [PROD_Release] WHERE No IN(SELECT No FROM [PROD_Release] WHERE [ProdNo_C] = '" + strGetProdC + "' AND [TestCodeNo] = "+ strGetTestCodeNo + " AND [VariantNo] = "+ strGetTestListNo + " ) ORDER BY No ASC;";
                        // 'C_ProdNo' // 'TestCodeNo' // 'VariantNo' // 'P_ProdNo' // 'FileVersion'
                        string strGetQueryText = 
                        $"SELECT X.No, " +
                        $"X.ProdNo_C AS 'C_ProdNo', " +
                        $"Y.No AS 'TestCodeNo', " +
                        $"Y.TestCode, " +
                        $"Z.No AS 'VariantNo', " +
                        $"Z.ProdNo_P AS 'P_ProdNo', " +
                        $"J.TestType, " +
                        $"J.Version AS 'FileVersion', " +
                        $"J.ProdCode, " +
                        $"X.Config, " +
                        $"X.RegDT, " +
                        $"X.RegUser, " +
                        $"X.RegUserComment " +
                        $"FROM [PROD_Release] AS X " +
                        $"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 [STOR_TestListFile] AS J WITH(NOLOCK) ON Z.TestListFileNo = J.No " +
                        $"WHERE X.ProdNo_C = '" + strGetProdC + "' AND X.TestCodeNo = " + strGetTestCodeNo + " " +
                        $"ORDER BY No ASC;";

                        DataTable dtCheck = ctrlDB.GetTable(strGetQueryText); 

                        if (XCommons.isHasRow(dtCheck))
                        {
                            bool bExistException = false;
                            bool bDetailInforSame = false;

                            string strTableProdNoC = dtCheck.Rows[0]["C_ProdNo"].ToString();
                            string strTableTestCode = dtCheck.Rows[0]["TestCode"].ToString();
                            string strTableTestType = dtCheck.Rows[0]["TestType"].ToString();
                            string strTableVersion = dtCheck.Rows[0]["FileVersion"].ToString();
                            string strTableProductionCode = dtCheck.Rows[0]["ProdCode"].ToString();

                            if (strGetProdC.CompareTo(strTableProdNoC) == 0 &&
                               strGetTestCode.CompareTo(strTableTestCode) == 0 &&
                               strGetTestType.CompareTo(strTableTestType) == 0 &&
                               strGetVersion.CompareTo(strTableVersion) == 0 &&
                               strGetProdCode.CompareTo(strTableProductionCode) == 0)
                            {
                                bExistException = true;

                                bDetailInforSame = true;
                            }
                         
                            if(CurrentWizardMode == eSelectMode.Modify)
                            {
                                if (strGetProdC.CompareTo(strGetModifyProdCInfo) == 0 &&
                                   strGetTestCodeNo.CompareTo(strGetModifyTestCodeInfo) == 0)
                                {
                                    if(strGetTestListNo.CompareTo(strGetModifyTestListInfo) != 0)
                                    {
                                        if(bDetailInforSame)
                                            bExistException = false;
                                    }
                                    else
                                        bExistException = false;
                                }
                            }

                            if(bExistException)
                            throw new Exception($"ProdNo_C - TestCode - TestType - Version - ProductionCode Combine Key is information that already exists. : " +
                                $"{textBoxItem1.Text}" + " " + $"{textBoxDispTestCode.Text}" + " " + $"{textBoxDispInTestType.Text}" + " " + $"{textBoxDispInVersion.Text}" + " " + $"{textBoxDispInProdCode.Text}");
                        }
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show(ex.Message, strTitle, MessageBoxButtons.OK, MessageBoxIcon.Warning);

                        e.Handled = true;

                        return;
                    }

                    labelControlInfo1.Text = textBoxItem1.Text;
                    labelControlInfo2.Text = textBoxItem4.Text;
                    labelControlInfo3.Text = textBoxItem5_Picker.Value.ToString("yyyy-MM-dd HH:mm:ss.fff");
                    labelControlInfo4.Text = textBoxItem6.Text;
                    labelControlInfo5.Text = textBoxItem7.Text;

                    switch (CurrentWizardMode)
                    {
                        case eSelectMode.Insert:
                            break;
                        case eSelectMode.Modify:
                            break;
                    }

                    string strGetItemNum1 = textBoxDispTestCodeNo.Text; 
                    string strGetItemNum2 = textBoxDispTestListVariantNo.Text; 

                    DataTable dtTestList =
                         ctrlDB.GetTable($"SELECT X.ProdNo_P, Y.TestType, Y.Version, Y.ProdCode, C.GroupName, C.ModelName, D.TestCode, D.Gate1, D.Gate2  FROM [PROD_Variant] AS X WITH(NOLOCK) " +
                        $"INNER JOIN(SELECT * FROM [PROD_Group] AS Y) AS C ON C.No = X.GroupNo " +
                        $"INNER JOIN(SELECT * FROM [STAT_TestCode] AS Z) AS D ON D.No = " + strGetItemNum1 + " " +
                        $"INNER JOIN [STOR_TestListFile] AS Y WITH(NOLOCK) ON X.TestListFileNo = Y.No " +
                        $"WHERE X.No = " + strGetItemNum2 + ";");

                    dataGridView.DataSource = dtTestList;

                    ctrlTestListRelInformation.ProdNo_C = textBoxItem1.Text;
                    ctrlTestListRelInformation.TestCodeNo = Commons.ConvertTextToTryValue<int>(strGetItemNum1, -1);
                    ctrlTestListRelInformation.VariantNo = Commons.ConvertTextToTryValue<int>(strGetItemNum2, -1);
                    ctrlTestListRelInformation.Config = textBoxItem4.Text;
                    ctrlTestListRelInformation.RegDT = textBoxItem5_Picker.Value;
                    ctrlTestListRelInformation.RegUser = textBoxItem6.Text;
                    ctrlTestListRelInformation.RegUserComment = textBoxItem7.Text;
                }
            }
        }

        private void buttonTestCodeChk_Click(object sender, EventArgs e)
        {
            TestCodeCheckResult = false;

            textBoxDispTestCodeNo.Text = "";
            textBoxDispTestCode.Text = "";
            textBoxDispGate1.Text = "";
            textBoxDispGate2.Text = "";
            textBoxDispComment.Text = "";

            DataTable dtTestCode = ctrlDB.GetTable("SELECT * FROM STAT_TestCode WHERE TestCode = '" + textBoxTextCodeInput.Text + "' ORDER BY No ASC;");

            if (XCommons.isHasRow(dtTestCode))
                CheckTestCodeInfo(dtTestCode);
        }

        private void buttonTestListChk_Click(object sender, EventArgs e)
        {
            TestListCheckResult = false;

            textBoxDispTestListVariantNo.Text = "";
            textBoxDispTestListComment.Text = "";
            textBoxDispTestListDescription.Text = "";

            string strSetQueryText = $"SELECT X.No, X.ProdNo_P, Y.TestType, Y.Version, Y.ProdCode, Y.FileName, X.Comment, X.Description FROM [PROD_Variant] AS X WITH(NOLOCK) " +
                    $"INNER JOIN [STOR_TestListFile] AS Y WITH(NOLOCK) ON X.TestListFileNo = Y.No " +
                    $"WHERE X.ProdNo_P = '" + textBoxPProdNoInput.Text + "' ";

            string strSetQueryEndText = "ORDER BY No ASC;";

            if (textBoxDispInTestType.Text.Length > 0)
            {
                strSetQueryText += "AND ";
                strSetQueryText += "Y.TestType = '" + textBoxDispInTestType.Text + "' ";
            }
            if (textBoxDispInVersion.Text.Length > 0)
            {
                strSetQueryText += "AND ";
                strSetQueryText += "Y.Version = '" + textBoxDispInVersion.Text + "' ";
            }
            if (textBoxDispInProdCode.Text.Length > 0)
            {
                strSetQueryText += "AND ";
                strSetQueryText += "Y.ProdCode = '" + textBoxDispInProdCode.Text + "' ";
            }
            if (textBoxDispInFileName.Text.Length > 0)
            {
                strSetQueryText += "AND ";
                strSetQueryText += "Y.FileName = '" + textBoxDispInFileName.Text + "' ";
            }

            strSetQueryText += strSetQueryEndText;

            DataTable dtTestList = ctrlDB.GetTable(strSetQueryText);

            if (XCommons.isHasRow(dtTestList))
            {
                if (CheckTestListInfo(dtTestList))
                {
                    wizardPage.ActiveControl = textBoxItem4;

                    textBoxItem4.Focus();
                }
            }
        }

        private void button_Click(object sender, EventArgs e)
        {
            int nTag = Convert.ToInt32(((Control)sender).Tag);

            switch(nTag)
            {
                case 0:
                    if (textBoxDispInTestType.ReadOnly) textBoxDispInTestType.ReadOnly = false;
                    else if (textBoxDispInTestType.ReadOnly == false) textBoxDispInTestType.ReadOnly = true;
                    break;
                case 1:
                    if (textBoxDispInVersion.ReadOnly) textBoxDispInVersion.ReadOnly = false;
                    else if(textBoxDispInVersion.ReadOnly == false) textBoxDispInVersion.ReadOnly = true;
                    break;
                case 2:
                    if (textBoxDispInProdCode.ReadOnly) textBoxDispInProdCode.ReadOnly = false;
                    else if(textBoxDispInProdCode.ReadOnly == false) textBoxDispInProdCode.ReadOnly = true;
                    break;
                case 3:
                    if (textBoxDispInFileName.ReadOnly) textBoxDispInFileName.ReadOnly = false;
                    else if(textBoxDispInFileName.ReadOnly == false) textBoxDispInFileName.ReadOnly = true;
                    break;
            }
        }

        private void textBoxDispIn_ReadOnlyChanged(object sender, EventArgs e)
        {
            int nTag = Convert.ToInt32(((Control)sender).Tag);

            bool bReadOnly = ((TextBox)sender).ReadOnly;

            switch (nTag)
            {          
                case 0:
                    if (bReadOnly) button1.BackColor = Color.Transparent;
                    else button1.BackColor = Color.Yellow; textBoxDispInTestType.Focus();
                    break;
                case 1:
                    if (bReadOnly) button2.BackColor = Color.Transparent;
                    else button2.BackColor = Color.Yellow; textBoxDispInVersion.Focus();
                    break;
                case 2:
                    if (bReadOnly) button3.BackColor = Color.Transparent;
                    else button3.BackColor = Color.Yellow; textBoxDispInProdCode.Focus();
                    break;
                case 3:
                    if (bReadOnly) button4.BackColor = Color.Transparent;
                    else button4.BackColor = Color.Yellow; textBoxDispInFileName.Focus();
                    break; 
            }
        }

        private void checkBoxAutoComplete_CheckedChanged(object sender, EventArgs e)
        {
            if (checkBoxAutoComplete.Checked == false)
            {
                textBoxPProdNoInput.AutoCompleteCustomSource = null;
                textBoxPProdNoInput.AutoCompleteMode = AutoCompleteMode.None;
                textBoxPProdNoInput.AutoCompleteSource = AutoCompleteSource.None;
            }
            else
            {
                /*if (checkBoxAutoComplete.Checked != true || textBoxPProdNoInput.Text.Length <= 0)
                    return;*/

                //WHERE ProdNo_P LIKE '%" + textBoxPProdNoInput.Text + "%'

                DataTable dtProdNoP = ctrlDB.GetTable("SELECT No, ProdNo_P FROM [PROD_Variant] ORDER BY No ASC;");

                if (dtProdNoP == null)
                    return;

                /*
                int nDataPos = 0;

                string[] strData = new string[dtProdNoP.Rows.Count];

                foreach (DataRow dr in dtProdNoP.Rows)
                {
                    strData[nDataPos] = dr["ProdNo_P"].ToString();

                    nDataPos++;
                }
                */

                string[] postSource = dtProdNoP
                    .AsEnumerable()
                    .Select<System.Data.DataRow, string>(x => x.Field<string>("ProdNo_P"))
                    .ToArray();

                var source = new AutoCompleteStringCollection();

                source.AddRange(postSource);

                textBoxPProdNoInput.AutoCompleteCustomSource = source;

                textBoxPProdNoInput.AutoCompleteMode = AutoCompleteMode.Suggest;
                textBoxPProdNoInput.AutoCompleteSource = AutoCompleteSource.CustomSource;
            }
        }

        private void textBoxPProdNoInput_TextChanged(object sender, EventArgs e)
        {
            TestListCheckResult = false;

            textBoxPProdNoInput.BackColor = Color.Yellow;

            textBoxDispInTestType.Text = "";
            textBoxDispInVersion.Text = "";
            textBoxDispInProdCode.Text = "";
            textBoxDispInFileName.Text = "";
        }

        private void textBoxDispIn_TextChanged(object sender, EventArgs e)
        {
            TestListCheckResult = false;

            textBoxPProdNoInput.BackColor = Color.Yellow;
        }

        private void textBoxTextCodeInput_TextChanged(object sender, EventArgs e)
        {
            TestCodeCheckResult = false;

            textBoxTextCodeInput.BackColor = Color.Yellow;
        }

        private void comboBoxTestCodeList_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (comboBoxTestCodeList.SelectedIndex > 0)
            {
                textBoxTextCodeInput.Text = comboBoxTestCodeList.Items[comboBoxTestCodeList.SelectedIndex].ToString();

                TestCodeCheckResult = false;

                textBoxTextCodeInput.BackColor = Color.Yellow;
            }
        }

        private void wizardControl_CustomizeCommandButtons(object sender, DevExpress.XtraWizard.CustomizeCommandButtonsEventArgs e)
        {
            if (e.Page == wizardPage)
            {
                this.ActiveControl = textBoxItem1;

                textBoxItem1.Focus();
            }
            else if (e.Page == welcomeWizardPage)
            {
                this.ActiveControl = e.NextButton.Button;

                e.NextButton.Button.Focus();
            }
        }
    }
}
