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

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

    public partial class MIL1553Form : Form
    {
        private Timer _timerUiUpdate;
        MajorFrame[] pFrame;

        /// Delegate function to use for message update in GUI
        //public delegate void MessageUpdateDelegate(string msgName, S16BIT devNum);
        // public delegate void MessageUpdateDelegate(string msgName);
        public delegate void MessageUpdateDelegate(Msg1553 msg);

        /// The delegated method for updating message
        public MessageUpdateDelegate mMessageDelegateCh1, mMessageDelegateCh2;

        public const U16BIT ACE_BC_BSW_ERRFLG = 0x1000;

        public const byte NUM_1553_CHANNELS = 2;

        ushort[] num1553Rows;  // no. of 1553 parameters to display

        List<CodedType> m_CodedTypes;

        ARINC429Form pFormArinc429;
        MainForm pFormMain;
        DataGridViewColumnSelector m_DataGridViewColSelectorCh1, m_DataGridViewColSelectorCh2;

        DDC1553Node[] pDDC1553Node;

        public MIL1553Form(MainForm pFormMainHdl)
        {
            InitializeComponent();

            //Create the delegate for the message update.
            mMessageDelegateCh1 = new MessageUpdateDelegate(UpdateMessageCh1);
            mMessageDelegateCh2 = new MessageUpdateDelegate(UpdateMessageCh2);

            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 (Msg1553 msg in pFrame[0].msgs)
            {
                UpdateMessageCh1(msg);
            }

            foreach (Msg1553 msg in pFrame[1].msgs)
            {
                UpdateMessageCh2(msg);
            }
        }

        //public void InitArinc429FormHdl(ARINC429Form pFormArinc429Hdl)
        public void InitParas(ARINC429Form pFormArinc429Hdl, DDC1553Node[] pParaDDC1553Node)
        {
            pFormArinc429 = pFormArinc429Hdl;
            pDDC1553Node = pParaDDC1553Node;
        }

        public void InitForm(MajorFrame[] majFrame, ushort[] paraNum1553Rows, List<CodedType> paraCodedTypes)
        {
            pFrame = majFrame;
            num1553Rows = paraNum1553Rows;
            m_CodedTypes = paraCodedTypes;

            DataGridView[] dataGrids_mil1553 = { dataGridView_mil1553_Ch1, dataGridView_mil1553_Ch2 };

            for (byte chNo = 0; chNo < NUM_1553_CHANNELS; chNo++)
            {
                dataGrids_mil1553[chNo].Rows.Clear();
                for (int ctr = 0; ctr < num1553Rows[chNo] - 1; ctr++)
                {
                    dataGrids_mil1553[chNo].Rows.Add();
                }

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

            _timerUiUpdate.Start();
        }

        /*******************************************************************************
         * Name:    UpdateMessage
         *
         * Description:
         *
         *      This is a delegate handler for the message posted by ThreadMsgGet
         * when it finds a message in the BC Host Buffer.
         * 
         * The handler processes the received message for user-friendly display 
         * in the GUI 
         *
         ******************************************************************************/
        //private void UpdateMessageCh1(string msgName)
        //{
        //    foreach (Msg1553 pMsg in pFrame[0].msgs)
        //    {
        //        if (pMsg.name == msgName)
        //        {
        //            //Msg1553 refMsg = new Msg1553();

        //            //bool retValBool = majFrame.FindMessageInList(msgName, ref refMsg);

        //            //if (retValBool)
        //            //{
        //            //    // Update parameter value display for Msg
        //            //    UpdateParameterValueDisplay(refMsg);
        //            //}
        //            UpdateParameterValueDisplayCh1(pMsg);

        //            break;
        //        }
        //    }
        //}

        UInt64 ch1ctr = 0;

        private void UpdateMessageCh1(Msg1553 msg)
        {
            Debug.WriteLine("Ch1 {0}", ch1ctr++);
            UpdateParameterValueDisplayCh1(msg);
        }

        void UpdateParameterValueDisplayCh1(Msg1553 pMsg)
        {
            //string timeStamp = pMsg.getCombinedTT().ToString();

            lock (pDDC1553Node[0]._arrayLock)
            {
                string timeStamp = pMsg.getFormattedTT();

                string status;
                if ((pMsg.getMsgRunTimeData().wBlkSts & ACE_BC_BSW_ERRFLG) == ACE_BC_BSW_ERRFLG)
                {
                    status = pDDC1553Node[0].GetAceBSWExtErrorStr(pMsg.getMsgRunTimeData().wBlkSts);
                }
                else
                {
                    status = "OK";
                }

                foreach (EguParameter pEguParam in pMsg.eguParams)
                {
                    //if (dataGridView1.Rows[pEguParam.displayRowNo].Displayed)
                    {
                        string paraValue = "";

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

                        dataGridView_mil1553_Ch1.Rows[pEguParam.displayRowNo].Cells[3].Value = paraValue;
                        dataGridView_mil1553_Ch1.Rows[pEguParam.displayRowNo].Cells[5].Value = timeStamp;
                        dataGridView_mil1553_Ch1.Rows[pEguParam.displayRowNo].Cells[6].Value = status;

                    }
                }
            }
        }

        UInt64 ch2ctr = 0;
        private void UpdateMessageCh2(Msg1553 msg)
        {
            Debug.WriteLine("Ch2 {0}", ch2ctr++);
            UpdateParameterValueDisplayCh2(msg);
        }

        void UpdateParameterValueDisplayCh2(Msg1553 pMsg)
        {
            //string timeStamp = pMsg.getCombinedTT().ToString();

            lock (pDDC1553Node[1]._arrayLock)   // Message list is accessed by ThreadMsgGet of DDC1553Node as well. Hence the lock
            {
                string timeStamp = pMsg.getFormattedTT();

                string status;
                if ((pMsg.getMsgRunTimeData().wBlkSts & ACE_BC_BSW_ERRFLG) == ACE_BC_BSW_ERRFLG)
                {
                    status = pDDC1553Node[1].GetAceBSWExtErrorStr(pMsg.getMsgRunTimeData().wBlkSts);
                }
                else
                {
                    status = "OK";
                }

                foreach (EguParameter pEguParam in pMsg.eguParams)
                {
                    //if (dataGridView1.Rows[pEguParam.displayRowNo].Displayed)
                    {
                        string paraValue = "";

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

                        dataGridView_mil1553_Ch2.Rows[pEguParam.displayRowNo].Cells[3].Value = paraValue;
                        dataGridView_mil1553_Ch2.Rows[pEguParam.displayRowNo].Cells[5].Value = timeStamp;
                        dataGridView_mil1553_Ch2.Rows[pEguParam.displayRowNo].Cells[6].Value = status;

                    }
                }
            }
        }

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

        private void MIL1553Form_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_ARINC429Form_Click(object sender, EventArgs e)
        {
            this.Hide();
            pFormArinc429.Show();
        }

        private void MIL1553Form_Load(object sender, EventArgs e)
        {
            for (int i = 0; i < dataGridView_mil1553_Ch1.Columns.Count; i++)
            {
                dataGridView_mil1553_Ch1.AutoResizeColumn(i);   // Parameter column
            }

            for (int i = 0; i < dataGridView_mil1553_Ch2.Columns.Count; i++)
            {
                dataGridView_mil1553_Ch2.AutoResizeColumn(i);   // Parameter column
            }

            m_DataGridViewColSelectorCh1 = new DataGridViewColumnSelector(dataGridView_mil1553_Ch1);
            m_DataGridViewColSelectorCh2 = new DataGridViewColumnSelector(dataGridView_mil1553_Ch2);

            label_title.Text = "ADU/ADC ATP Testing - MIL-STD-1553 Parameters";

            this.ControlBox = true;
        }
    }
}
