using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace arinc_1553_CSharpGUI
{
    using U64BIT = System.UInt64;
    using U32BIT = System.UInt32;
    using U16BIT = System.UInt16;
    using U8BIT = System.Byte;
    using S64BIT = System.Int64;
    using S32BIT = System.Int32;
    using S16BIT = System.Int16;
    using S8BIT = System.SByte;

    public enum ArincConfiguration
    {
        LowSpeed_Channel1,
        HighSpeed_Channel1,
        LowSpeed_Channel2,
        HighSpeed_Channel2,
        LowSpeed_Channel1_2,
        HighSpeed_Channel1_2
    }

    public enum Mil1553Configuration
    {
        Channel1,
        Channel2,
        Channel1_2
    }

    public partial class MainForm : Form
    {
        public const U8BIT NUM_1553_CHANNELS = 2;

        DDC1553Node[] pDDC1553Node = new DDC1553Node[NUM_1553_CHANNELS];
        DDCARINC429 pDDCARINC429;
        MajorFrame[] majFrame = new MajorFrame[NUM_1553_CHANNELS];
        List<MsgArinc429> arincMsgs;
        List<CodedType> m_CodedTypes;

        ushort[] num1553Rows = new ushort[NUM_1553_CHANNELS];  // no. of 1553 parameters to display
        ushort numArincRowsChan1, numArincRowsChan2;  // no. of Arinc parameters to display

        bool isReadExcelFile = false;

        MIL1553Form mil1553Form;
        ARINC429Form arinc429Form;
        BuiltInTestForm builtInTestForm;

        OpenFileDialog openFileDialog;
        U16BIT defaultTTRes = ddc1553Constants.TTResValues.ACE_TT_4US;

        string LRU_Part_No, LRU_Serial_No;

        SemaphoreSlim APILock = new SemaphoreSlim(1);

        public MainForm()
        {
            InitializeComponent();

            mil1553Form = new MIL1553Form(this);
            arinc429Form = new ARINC429Form(this);
            builtInTestForm = new BuiltInTestForm(this);
            for(S16BIT ctr = 0; ctr < NUM_1553_CHANNELS; ctr++)
            {
                pDDC1553Node[ctr] = new DDC1553Node(ctr, builtInTestForm, APILock);
            }
            pDDCARINC429 = new DDCARINC429(1, builtInTestForm);

            openFileDialog = new OpenFileDialog();

            // Configure the dialog
            openFileDialog.Title = "Select a File";
            openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // Start in My Documents
            openFileDialog.Filter = "Xls files (*.xls)|*.xls|Xlsx files (*.xlsx)|*.xlsx|All files (*.*)|*.*"; // Filter for text and all files
            openFileDialog.FilterIndex = 2; // Default to text files
            openFileDialog.RestoreDirectory = true; // Restore last used directory

            //mil1553Form.InitArinc429FormHdl(arinc429Form);
            mil1553Form.InitParas(arinc429Form, pDDC1553Node);
            arinc429Form.InitParas(mil1553Form, pDDCARINC429);

            comboBoxARINCConfig.DataSource = Enum.GetValues(typeof(ArincConfiguration));

            comboBoxMIL1553Config.DataSource = Enum.GetValues(typeof(Mil1553Configuration));
        }

        private void buttonBuiltInTest_Click(object sender, EventArgs e)
        {
            if (buttonStartStop.Text == "Stop\r\nComm")
            {
                MessageBox.Show("Please click Stop first!",
                                    "BuiltInTest error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            HideAllOpenForms();

            builtInTestForm.Show();

            for (S16BIT ctr = 0; ctr < NUM_1553_CHANNELS; ctr++)
            {
                pDDC1553Node[ctr].DoSelfTest(ctr);
            }

            //pDDCARINC429.DoSelfTest(1);
        }

        private void buttonReadConfigFile_Click(object sender, EventArgs e)
        {
            if (buttonStartStop.Text == "Stop\r\nComm")
            {
                MessageBox.Show("Please click Stop first!",
                                    "ReadConfigFile error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            for (S16BIT ctr = 0; ctr < NUM_1553_CHANNELS; ctr++)
            {
                majFrame[ctr] = new MajorFrame();
            }

            arincMsgs = new List<MsgArinc429>();

            m_CodedTypes = new List<CodedType>();

            ReadExcel pExcel = new ReadExcel(textBoxFilePath.Text, ref majFrame, ref arincMsgs);

            if (!pExcel.InitExcelRead())
            {
                MessageBox.Show("Error in InitExcelRead.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            /* Read general info from the configuration Excel file */
            if (!pExcel.ReadGeneralSheetFromExcel(out LRU_Part_No, out LRU_Serial_No))
            {
                MessageBox.Show("Error in ReadGeneralSheetFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            /* Read 1553 messages, frames and other info from the configuration Excel file */
            if (!pExcel.Read1553MessageListFromExcel())
            {
                MessageBox.Show("Error in ReadMessageListFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            if (!pExcel.ReadCodedTypesFromExcel(ref m_CodedTypes))
            {
                MessageBox.Show("Error in ReadCodedTypesFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            if (!pExcel.Read1553ParameterListFromExcel(ref num1553Rows, m_CodedTypes))
            {
                MessageBox.Show("Error in ReadParameterListFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            if (!pExcel.ReadFrameListFromExcel(0))
            {
                MessageBox.Show("Error in ReadFrameListFromExcel 0.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            if (!pExcel.ReadFrameListFromExcel(1))
            {
                MessageBox.Show("Error in ReadFrameListFromExcel 1.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            /* Read Arinc messages and other info from the configuration Excel file */
            if (!pExcel.ReadArincMessageListFromExcel())
            {
                MessageBox.Show("Error in ReadArincMessageListFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }
            if (!pExcel.ReadArincParameterListFromExcel(ref numArincRowsChan1, ref numArincRowsChan2, m_CodedTypes))
            {
                MessageBox.Show("Error in ReadArincParameterListFromExcel.",
                                        "Config file error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                pExcel.DeInitExcelRead();

                return;
            }

            MessageBox.Show("Reading Excel file successful!",
                                        "Config file read", MessageBoxButtons.OK);

            pExcel.DeInitExcelRead();

            isReadExcelFile = true;
            buttonReadConfigFile.Image = Properties.Resources.Load_Config;

            //dataGridView1.Rows.Clear();
            //for (int ctr = 0; ctr < num1553Rows - 1; ctr++)
            //{
            //    dataGridView1.Rows.Add();
            //}

            //foreach (Msg1553 pMsg in majFrame.msgs)
            //{
            //    foreach (EguParameter pEguParam in pMsg.eguParams)
            //    {
            //        dataGridView1.Rows[pEguParam.displayRowNo].Cells[0].Value = pEguParam.displayRowNo + 1;
            //        dataGridView1.Rows[pEguParam.displayRowNo].Cells[1].Value = pEguParam.name;
            //        dataGridView1.Rows[pEguParam.displayRowNo].Cells[2].Value = pEguParam.pMsg.name;
            //        dataGridView1.Rows[pEguParam.displayRowNo].Cells[4].Value = pEguParam.units;
            //    }
            //}

            //dataGridView2.Rows.Clear();
            //for (int ctr = 0; ctr < numArincRows - 1; ctr++)
            //{
            //    dataGridView2.Rows.Add();
            //}

            //foreach (MsgArinc429 pMsgArinc in arincMsgs)
            //{
            //    foreach (EguParameterArinc429 pEguParam in pMsgArinc.eguParams)
            //    {
            //        dataGridView2.Rows[pEguParam.displayRowNo].Cells[0].Value = pEguParam.displayRowNo + 1;
            //        dataGridView2.Rows[pEguParam.displayRowNo].Cells[1].Value = pEguParam.name;
            //        dataGridView2.Rows[pEguParam.displayRowNo].Cells[2].Value = pEguParam.pMsg.labelName;
            //        dataGridView2.Rows[pEguParam.displayRowNo].Cells[4].Value = pEguParam.units;
            //    }
            //}
        }

        private void buttonStartStop_Click(object sender, EventArgs e)
        {
            U8BIT start1553Chan, end1553Chan;
            if (comboBoxMIL1553Config.SelectedIndex == (int)Mil1553Configuration.Channel1)
            {
                start1553Chan = end1553Chan = 0;
            }
            else if (comboBoxMIL1553Config.SelectedIndex == (int)Mil1553Configuration.Channel2)
            {
                start1553Chan = end1553Chan = 1;
            }
            else
            {
                start1553Chan = 0;
                end1553Chan = 1;
            }

            if (buttonStartStop.Text == "Start\r\nComm")
            {
                if (!isReadExcelFile)
                {
                    MessageBox.Show("Please read configuration file first!",
                                        "Start error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                    return;
                }
                else
                {
                    if(radioButtonMil1553.Checked || radioButtonBoth.Checked)
                    {
                        mil1553Form.InitForm(majFrame, num1553Rows, m_CodedTypes);

                        for (U8BIT ctr = start1553Chan; ctr <= end1553Chan; ctr++)
                        {
                            pDDC1553Node[ctr].InitDDC1553Node(ref majFrame[ctr], mil1553Form, m_CodedTypes);

                            if (pDDC1553Node[ctr].Initialize() != 0)
                            {
                                MessageBox.Show("Error in device initialization. Ensure LDN is set correctly in DDC Card Manager!",
                                                        "Init BC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }

                            if (pDDC1553Node[ctr].SetupBC() != ddc1553Constants.ApiErrorCodes.ACE_ERR_SUCCESS)
                            {
                                MessageBox.Show("Error in configuring BC",
                                                        "Init BC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }

                            if (pDDC1553Node[ctr].SetTimeTagRes(defaultTTRes) != ddc1553Constants.ApiErrorCodes.ACE_ERR_SUCCESS)
                            {
                                MessageBox.Show("Error in SetTimeTagRes",
                                                        "Init BC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }
                        }

                        for (U8BIT ctr = start1553Chan; ctr <= end1553Chan; ctr++)
                        {
                            if (pDDC1553Node[ctr].StartBC(-1) != 0)
                            {
                                MessageBox.Show("Error in starting BC",
                                                        "StartBC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }

                            MessageBox.Show("BC started successful!",
                                                        "Start BC", MessageBoxButtons.OK);
                        }
                    }

                    if (radioButtonArinc429.Checked || radioButtonBoth.Checked)
                    {
                        arinc429Form.InitForm(arincMsgs, numArincRowsChan1, numArincRowsChan2, m_CodedTypes, LRU_Part_No, LRU_Serial_No);

                        pDDCARINC429.InitDDCARINC429(ref arincMsgs, arinc429Form, m_CodedTypes, comboBoxARINCConfig.SelectedIndex);

                        if (pDDCARINC429.InitCard() != 0)
                        {
                            MessageBox.Show("Error in InitCard. Ensure ARINC 429 card number is set correctly in DDC Card Manager!",
                                                    "Init ARINC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                            return;
                        }

                        MessageBox.Show("ARINC 429 card initialisation completed successfully!",
                                                    "Init ARINC", MessageBoxButtons.OK);

                        pDDCARINC429.StartReception();
                    }

                    buttonStartStop.Text = "Stop\r\nComm";
                    buttonStartStop.Image = Properties.Resources.Comm_On;

                    radioButtonMil1553.Enabled = false;
                    radioButtonArinc429.Enabled = false;
                    radioButtonBoth.Enabled = false;

                    comboBoxARINCConfig.Enabled = false;
                    comboBoxMIL1553Config.Enabled = false;
                }
            }
            else if (buttonStartStop.Text == "Stop\r\nComm")
            {
                if (radioButtonMil1553.Checked || radioButtonBoth.Checked)
                {
                    for (U8BIT ctr = start1553Chan; ctr <= end1553Chan; ctr++)
                    {
                        if (pDDC1553Node[ctr].StopBC() != 0)
                        {
                            MessageBox.Show("Error in StopBC.",
                                                    "StopBC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                            return;
                        }

                        if (pDDC1553Node[ctr].Free() != 0)
                        {
                            MessageBox.Show("Error in FreeBC.",
                                                    "FreeBC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                            return;
                        }

                        MessageBox.Show("Free BC successful!",
                                                    "FreeBC", MessageBoxButtons.OK);
                    }
                }

                if (radioButtonArinc429.Checked || radioButtonBoth.Checked)
                {
                    pDDCARINC429.StopReception();

                    if (pDDCARINC429.FreeCard() != 0)
                    {
                        MessageBox.Show("Error in FreeCard.",
                                                "Free Arinc error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                        return;
                    }

                    MessageBox.Show("ARINC 429 card de-initialised successfully!",
                                                "ARINC De-init", MessageBoxButtons.OK);
                }

                buttonStartStop.Text = "Start\r\nComm";
                buttonStartStop.Image = Properties.Resources.Comm_Off;

                radioButtonMil1553.Enabled = true;
                radioButtonArinc429.Enabled = true;
                radioButtonBoth.Enabled = true;

                comboBoxARINCConfig.Enabled = true;
                comboBoxMIL1553Config.Enabled = true;
            }
        }

        private void button_Tx_Click(object sender, EventArgs e)
        {
            //uint num;
            //try
            //{
            //    num = uint.Parse(textBoxHexData.Text, System.Globalization.NumberStyles.AllowHexSpecifier);

            //    //MessageBox.Show("Valid data value entered.", "ARINC 429 Transmit Message", MessageBoxButtons.OK);

            //    if (pDDCARINC429.TxData(Byte.Parse(comboBox_TxChannel.SelectedItem.ToString()), num) != 1)
            //    {
            //        MessageBox.Show("Error in Tx Data.",
            //                                "Tx Arinc error", MessageBoxButtons.OK, MessageBoxIcon.Error);

            //        return;
            //    }

            //    MessageBox.Show("Tx Data successful!",
            //                                "Tx Data Arinc", MessageBoxButtons.OK);
            //}
            //catch
            //{
            //    MessageBox.Show("Invalid Tx Channel or Invalid data value entered. Please select a Tx Channel or enter a valid hex value.", "ARINC 429 Transmit Message", MessageBoxButtons.OK, MessageBoxIcon.Stop);

            //    textBoxHexData.Focus();
            //    textBoxHexData.SelectAll();
            //}
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            U8BIT start1553Chan, end1553Chan;
            if (comboBoxMIL1553Config.SelectedIndex == (int)Mil1553Configuration.Channel1)
            {
                start1553Chan = end1553Chan = 0;
            }
            else if (comboBoxMIL1553Config.SelectedIndex == (int)Mil1553Configuration.Channel2)
            {
                start1553Chan = end1553Chan = 1;
            }
            else
            {
                start1553Chan = 0;
                end1553Chan = 1;
            }

            //Environment.Exit(0);
            DialogResult res;
            res = MessageBox.Show("Are you sure you wish to close the application?", "Close reconfirmation", MessageBoxButtons.YesNo);

            if (res == DialogResult.Yes)
            {
                Properties.Settings.Default.ConfigFilePath = textBoxFilePath.Text;
                Properties.Settings.Default.ARINC429ConfigSelection = comboBoxARINCConfig.SelectedIndex;
                Properties.Settings.Default.MIL1553ConfigSelection = comboBoxMIL1553Config.SelectedIndex;
                Properties.Settings.Default.Save();

                if (buttonStartStop.Text == "Stop\r\nComm")
                {
                    if (radioButtonMil1553.Checked || radioButtonBoth.Checked)
                    {
                        for (U8BIT ctr = start1553Chan; ctr <= end1553Chan; ctr++)
                        {
                            if (pDDC1553Node[ctr].StopBC() != 0)
                            {
                                MessageBox.Show("Error in StopBC.",
                                                        "StopBC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }

                            /*MessageBox.Show("StopBC successful!",
                                                        "StopBC", MessageBoxButtons.OK);*/

                            if (pDDC1553Node[ctr].Free() != 0)
                            {
                                MessageBox.Show("Error in FreeBC.",
                                                        "FreeBC error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                                return;
                            }

                            /*MessageBox.Show("FreeBC successful!",
                                                        "FreeBC", MessageBoxButtons.OK);*/
                        }
                    }

                    if (radioButtonArinc429.Checked || radioButtonBoth.Checked)
                    {
                        pDDCARINC429.StopReception();

                        if (pDDCARINC429.FreeCard() != 0)
                        {
                            MessageBox.Show("Error in FreeCard.",
                                                    "Free Arinc error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                            return;
                        }

                        /*MessageBox.Show("Free Arinc successful!",
                                                    "Free Arinc", MessageBoxButtons.OK);*/
                    }
                }
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void button_ArincTest_Click(object sender, EventArgs e)
        {
            ArincTestForm arincTestForm = new ArincTestForm(pDDCARINC429.u8NumTx, pDDCARINC429);
            arincTestForm.Show();
        }

        private void buttonBrowseFile_Click(object sender, EventArgs e)
        {
            //OpenFileDialog openFileDialog = new OpenFileDialog();

            //// Configure the dialog
            //openFileDialog.Title = "Select a File";
            //openFileDialog.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments); // Start in My Documents
            //openFileDialog.Filter = "Xls files (*.xls)|*.xls|Xlsx files (*.xlsx)|*.xlsx|All files (*.*)|*.*"; // Filter for text and all files
            //openFileDialog.FilterIndex = 2; // Default to text files
            //openFileDialog.RestoreDirectory = true; // Restore last used directory

            if (buttonStartStop.Text == "Stop\r\nComm")
            {
                MessageBox.Show("Please click Stop first!",
                                    "BrowseConfigFile error", MessageBoxButtons.OK, MessageBoxIcon.Error);

                return;
            }

            // Show the dialog
            if (openFileDialog.ShowDialog() == DialogResult.OK)
            {
                // Get the selected file path
                string selectedFilePath = openFileDialog.FileName;
                    
                // Display the path (assuming you have a TextBox named txtFilePath)
                textBoxFilePath.Text = selectedFilePath;

                // You can now use selectedFilePath for further operations, like reading the file content
                // Example: string fileContent = System.IO.File.ReadAllText(selectedFilePath);
            }
        }

        private void button_Mil1553Form_Click(object sender, EventArgs e)
        {
            HideAllOpenForms();

            mil1553Form.Show();
        }

        private void button_ARINC429Form_Click(object sender, EventArgs e)
        {
            HideAllOpenForms();

            arinc429Form.Show();
        }

        // If you need to hide all open forms
        public void HideAllOpenForms()
        {
            Form[] openForms = Application.OpenForms.Cast<Form>().ToArray();

            foreach (Form form in openForms)
            {
                if(form.Name != "ArincTestForm")
                    form.Hide();
            }
        }

        private void radioButtonArinc429_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonArinc429.Checked)
            {
                comboBoxARINCConfig.Enabled = true;
                comboBoxMIL1553Config.Enabled = false;
            }
        }

        private void radioButtonBoth_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonBoth.Checked)
            {
                comboBoxARINCConfig.Enabled = true;
                comboBoxMIL1553Config.Enabled = true;
            }
        }

        private void radioButtonMil1553_CheckedChanged(object sender, EventArgs e)
        {
            if (radioButtonMil1553.Checked)
            {
                comboBoxARINCConfig.Enabled = false;
                comboBoxMIL1553Config.Enabled = true;
            }
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            textBoxFilePath.Text = Properties.Settings.Default.ConfigFilePath;
            comboBoxARINCConfig.SelectedIndex = Properties.Settings.Default.ARINC429ConfigSelection;
            comboBoxMIL1553Config.SelectedIndex = Properties.Settings.Default.MIL1553ConfigSelection;
            comboBoxARINCConfig.Enabled = false;    /* We start with MIL-1553 as default and hence disable this combo */
        }

        private void button_Close_Click(object sender, EventArgs e)
        {
            //DialogResult res;
            //res = MessageBox.Show("Are you sure you wish to close the application?", "Close reconfirmation", MessageBoxButtons.YesNo);

            //if (res == DialogResult.Yes)
            //{
                this.Close();
            //}
        }
    }
}
