using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
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 partial class ARINC429Form : Form
    {
        private Timer _timerUiUpdate;
        List<MsgArinc429> arincMsgs;

        /// Delegate function to use for message update in GUI
        //public delegate void RxUpdateDelegate(string dataString, string timeStampStr, string labelName, U8BIT chanNum);

        /// The delegated method for updating message
        //public RxUpdateDelegate mRxDelegate;

        ushort numArincRowsChan1, numArincRowsChan2;  // no. of Arinc parameters to display

        List<CodedType> m_CodedTypes;

        MIL1553Form pFormMil1553;
        MainForm pFormMain;
        DataGridViewColumnSelector m_DataGridViewColSelectorChan1, m_DataGridViewColSelectorChan2;
        string lruPartNo, lruSerialNo;

        DDCARINC429 pDDCARINC429;

        public ARINC429Form(MainForm pFormMainHdl)
        {
            InitializeComponent();

            //Create the delegate for the message update.
            //mRxDelegate = new RxUpdateDelegate(UpdateRx);

            pFormMain = pFormMainHdl;

            SetupTimer();
        }

        private void SetupTimer()
        {
            _timerUiUpdate = new Timer();
            _timerUiUpdate.Interval = 100; // 100 milliseconds
            _timerUiUpdate.Tick += TimerUiUpdate;
        }

        private void TimerUiUpdate(object sender, EventArgs e)
        {
            foreach (MsgArinc429 pMsg in arincMsgs)
            {
                UpdateRx(pMsg);
            }
        }

        public void InitParas(MIL1553Form pFormMil1553Hdl, DDCARINC429 pParaDDCARINC429)
        {
            pFormMil1553 = pFormMil1553Hdl;
            pDDCARINC429 = pParaDDCARINC429;
        }

        public void InitForm(List<MsgArinc429> paraArincMsgs, ushort paraNumArincRowsChan1, ushort paraNumArincRowsChan2, List<CodedType> paraCodedTypes, string lruPartNo, string lruSerialNo)
        {
            arincMsgs = paraArincMsgs;
            numArincRowsChan1 = paraNumArincRowsChan1;
            numArincRowsChan2 = paraNumArincRowsChan2;
            m_CodedTypes = paraCodedTypes;

            dataGridView_arinc429Chan1.Rows.Clear();
            for (int ctr = 0; ctr < numArincRowsChan1 - 1; ctr++)
            {
                dataGridView_arinc429Chan1.Rows.Add();
            }

            foreach (MsgArinc429 pMsgArinc in arincMsgs)
            {
                if(pMsgArinc.channel == "1" || pMsgArinc.channel == "Both")
                {
                    foreach (EguParameterArinc429 pEguParam in pMsgArinc.eguParams)
                    {
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[0].Value = pEguParam.displayRowNoChan1 + 1;
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[1].Value = pEguParam.name;
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[2].Value = Convert.ToString(pEguParam.pMsg.labelValue, 8);
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[3].Value = pEguParam.pMsg.labelName;
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[5].Value = pEguParam.units;
                    }
                }
            }

            dataGridView_arinc429Chan2.Rows.Clear();
            for (int ctr = 0; ctr < numArincRowsChan2 - 1; ctr++)
            {
                dataGridView_arinc429Chan2.Rows.Add();
            }

            foreach (MsgArinc429 pMsgArinc in arincMsgs)
            {
                if (pMsgArinc.channel == "2" || pMsgArinc.channel == "Both")
                {
                    foreach (EguParameterArinc429 pEguParam in pMsgArinc.eguParams)
                    {
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[0].Value = pEguParam.displayRowNoChan2 + 1;
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[1].Value = pEguParam.name;
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[2].Value = Convert.ToString(pEguParam.pMsg.labelValue, 8);
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[3].Value = pEguParam.pMsg.labelName;
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[5].Value = pEguParam.units;
                    }
                }
            }

            this.lruPartNo = lruPartNo;
            this.lruSerialNo = lruSerialNo;

            labelLruPartNo.Text = lruPartNo;
            labelLruSerialNo.Text = lruSerialNo;

            _timerUiUpdate.Start();
        }

        /*******************************************************************************
         * Name:    UpdateRx
         *
         * Description:
         *
         *      This is a delegate handler for the Rx message posted by ThreadRx
         * when it finds a Rx message in the Rx Host Buffer.
         * 
         * The handler processes the received Rx message for user-friendly display 
         * in the GUI 
         *
         ******************************************************************************/
        private void UpdateRx(MsgArinc429 pMsg)
        {
            UpdateArincParameterValueDisplay(pMsg);
        }

        void UpdateArincParameterValueDisplay(MsgArinc429 pMsg)
        {
            lock (pDDCARINC429._arrayLock)
            {
                foreach (EguParameterArinc429 pEguParam in pMsg.eguParams)
                {
                    string paraValue = "";

                    if (pEguParam.dataType.ToUpper() == "CODED")
                    {
                        paraValue = pEguParam.value.strValue;
                    }
                    else
                    {
                        paraValue = pEguParam.value.fValue.ToString();
                    }

                    // If the latest attempt to compute this parameter was invalid, then the value of this parameter
                    // is stale. Signal this to the user by adding an exclamation at the end of the value
                    if (!pEguParam.isValid)
                    {
                        paraValue += "!";
                    }

                    if (pMsg.getChannelNum() == 1)
                    {
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[4].Value = paraValue;
                        dataGridView_arinc429Chan1.Rows[pEguParam.displayRowNoChan1].Cells[6].Value = pMsg.getFormattedTT();
                    }
                    else if(pMsg.getChannelNum() == 2)
                    {
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[4].Value = paraValue;
                        dataGridView_arinc429Chan2.Rows[pEguParam.displayRowNoChan2].Cells[6].Value = pMsg.getFormattedTT();
                    }
                }
            }
        }

        private void ARINC429Form_FormClosing(object sender, FormClosingEventArgs e)
        {
            // Force user to navigate to the main from and close application from there only
            e.Cancel = true;
            this.Hide();
            pFormMain.Show();
        }

        private void button_MainForm_Click(object sender, EventArgs e)
        {
            this.Hide();
            pFormMain.Show();
        }

        private void button_Mil1553Form_Click(object sender, EventArgs e)
        {
            this.Hide();
            pFormMil1553.Show();
        }

        private void label2_Click(object sender, EventArgs e)
        {

        }

        private void ARINC429Form_Load(object sender, EventArgs e)
        {
            m_DataGridViewColSelectorChan1 = new DataGridViewColumnSelector(dataGridView_arinc429Chan1);
            m_DataGridViewColSelectorChan2 = new DataGridViewColumnSelector(dataGridView_arinc429Chan2);
            label_title.Text = "ADU/ADC ATP Testing - ARINC 429 Parameters";
            this.ControlBox = true;
        }
    }
}
