using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
/// <summary>
/// Inclusion of PEAK PCAN-Basic namespace
/// </summary>
using TPCANHandle = System.UInt16;
using TPCANBitrateFD = System.String;
using TPCANTimestampFD = System.UInt64;

namespace SIASUN.Autopilot.Device
{
    /// <summary>
    /// Message Status structure used to show CAN Messages
    /// in a ListView
    /// </summary>
    public class MessageStatus
    {
        private TPCANMsgFD m_Msg;
        private TPCANTimestampFD m_TimeStamp = 0;
        private TPCANTimestampFD m_oldTimeStamp = 0;

        public MessageStatus(TPCANMsgFD canMsg, TPCANTimestampFD canTimestamp)
        {
            m_Msg = canMsg;
            m_TimeStamp = canTimestamp;
            m_oldTimeStamp = canTimestamp;
        }

        public void Update(TPCANMsgFD canMsg, TPCANTimestampFD canTimestamp)
        {
            m_Msg = canMsg;
            m_TimeStamp = canTimestamp;
            m_oldTimeStamp = canTimestamp;
        }

        public TPCANMsgFD CANMsg
        {
            get { return m_Msg; }
        }

        public TPCANTimestampFD Timestamp
        {
            get { return m_TimeStamp; }
        }


        public string TypeString
        {
            get { return GetMsgTypeString(); }
        }

        public string IdString
        {
            get { return GetIdString(); }
        }

        public string DataString
        {
            get { return GetDataString(); }
        }


        public string TimeString
        {
            get { return GetTimeString(); }
        }


        private string GetTimeString()
        {
            double fTime;

            fTime = (m_TimeStamp / 1000.0);
            //if (m_bShowPeriod)
            //    fTime -= (m_oldTimeStamp / 1000.0);
            return fTime.ToString("F1");
        }

        private string GetDataString()
        {
            string strTemp;

            strTemp = "";

            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_RTR) == TPCANMessageType.PCAN_MESSAGE_RTR)
                return "Remote Request";
            else
                for (int i = 0; i < GetLengthFromDLC(m_Msg.DLC, (m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_FD) == 0); i++)
                    strTemp += string.Format("{0:X2} ", m_Msg.DATA[i]);

            return strTemp;
        }

        private string GetIdString()
        {
            // We format the ID of the message and show it
            //
            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_EXTENDED) == TPCANMessageType.PCAN_MESSAGE_EXTENDED)
                return string.Format("{0:X8}", m_Msg.ID);
            else
                return string.Format("{0:X3}", m_Msg.ID);
        }

        private string GetMsgTypeString()
        {
            string strTemp;

            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_STATUS) == TPCANMessageType.PCAN_MESSAGE_STATUS)
                return "STATUS";

            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_ERRFRAME) == TPCANMessageType.PCAN_MESSAGE_ERRFRAME)
                return "ERROR";

            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_EXTENDED) == TPCANMessageType.PCAN_MESSAGE_EXTENDED)
                strTemp = "EXT";
            else
                strTemp = "STD";

            if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_RTR) == TPCANMessageType.PCAN_MESSAGE_RTR)
                strTemp += "/RTR";
            else
                if ((int)m_Msg.MSGTYPE > (int)TPCANMessageType.PCAN_MESSAGE_EXTENDED)
            {
                strTemp += " [ ";
                if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_FD) == TPCANMessageType.PCAN_MESSAGE_FD)
                    strTemp += " FD";
                if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_BRS) == TPCANMessageType.PCAN_MESSAGE_BRS)
                    strTemp += " BRS";
                if ((m_Msg.MSGTYPE & TPCANMessageType.PCAN_MESSAGE_ESI) == TPCANMessageType.PCAN_MESSAGE_ESI)
                    strTemp += " ESI";
                strTemp += " ]";
            }

            return strTemp;
        }

        #region Help functions
        /// <summary>
        /// Convert a CAN DLC value into the actual data length of the CAN/CAN-FD frame.
        /// </summary>
        /// <param name="dlc">A value between 0 and 15 (CAN and FD DLC range)</param>
        /// <param name="isSTD">A value indicating if the msg is a standard CAN (FD Flag not checked)</param>
        /// <returns>The length represented by the DLC</returns>
        private int GetLengthFromDLC(int dlc, bool isSTD)
        {
            if (dlc <= 8)
                return dlc;

            if (isSTD)
                return 8;

            switch (dlc)
            {
                case 9: return 12;
                case 10: return 16;
                case 11: return 20;
                case 12: return 24;
                case 13: return 32;
                case 14: return 48;
                case 15: return 64;
                default: return dlc;
            }
        }
        #endregion help functions

    }
}
