//                           UNCLASSIFIED
/*-------------------------------------------------------------------------
RAYTHEON PROPRIETARY: THIS DOCUMENT CONTAINS DATA OR INFORMATION
PROPRIETARY TO RAYTHEON COMPANY AND IS RESTRICTED TO USE ONLY BY PERSONS
AUTHORIZED BY RAYTHEON COMPANY IN WRITING TO USE IT. DISCLOSURE TO
UNAUTHORIZED PERSONS WOULD LIKELY CAUSE SUBSTANTIAL COMPETITIVE HARM TO
RAYTHEON COMPANY'S BUSINESS POSITION. NEITHER SAID DOCUMENT NOR ITS
CONTENTS SHALL BE FURNISHED OR DISCLOSED TO OR COPIED OR USED BY PERSONS
OUTSIDE RAYTHEON COMPANY WITHOUT THE EXPRESS WRITTEN APPROVAL OF RAYTHEON
COMPANY.

THIS PROPRIETARY NOTICE IS NOT APPLICABLE IF DELIVERED TO THE U.S.
GOVERNMENT.

UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
-------------------------------------------------------------------------*/

using System;
using System.Runtime.InteropServices;
using Raytheon.Common;

namespace FpgaMeasurementInstrumentsLib
{
   /// <summary>
   /// A message to read a register of the FPGA
   /// </summary>
   internal class FPGAReadRegisterCmdBlockIncrMessage : FPGACmdMessage
   {
      #region PrivateClassMembers

      [StructLayout(LayoutKind.Sequential, Pack = 1)]
      private struct Data
      {
         public uint m_address;
      };

      private Data m_dataStruct;

      //Dummy Array used to identify how much data will be sent back
      private byte[] m_data;

      private bool m_byteSwap;
      #endregion

      #region PrivateFunctions

      /// <summary>
      /// Create a copy of this object
      /// </summary>
      /// <returns>A copy of this object</returns>
      protected override object CloneSelf()
      {
         FPGAReadRegisterCmdBlockIncrMessage msg = new FPGAReadRegisterCmdBlockIncrMessage(this);

         return msg;
      }

      /// <summary>
      /// Encode the message into a byte array for sending.
      /// </summary>
      /// <param name="pData">The buffer to put the message items</param>
      protected override void FormatData(IntPtr pData)
      {
         try
         {
            // perform byte swapping and copy data into the buffer
            Data dataTemp = m_dataStruct;

            //Swap address bytes
            dataTemp.m_address = Util.Swap(dataTemp.m_address);

            //Create a pointer to message we want to send
            Marshal.StructureToPtr(dataTemp, pData, true);

            //Increment pointer to account for the m_dataStruct struct
            pData = IntPtr.Add(pData, Marshal.SizeOf(typeof(Data)));

            //Copy array into pointer
            Marshal.Copy(m_data, 0, pData, m_data.Length);
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// 
      /// </summary>
      /// <returns></returns>
      protected override int GetPayloadSize()
      {
         return Marshal.SizeOf(m_dataStruct) + m_data.Length;
      }

      /// <summary>
      /// Takes an array of bytes and populates the message object
      /// </summary>
      /// <param name="pData">The message in byte form</param>
      protected override void ParseData(IntPtr pData)
      {
         try
         {
            // copy data into our structure
            m_dataStruct = (Data)(Marshal.PtrToStructure(pData, typeof(Data)));

            //Increment point address to end of structure
            pData = IntPtr.Add(pData, Marshal.SizeOf(typeof(Data)));

            //Copy data from pointer to array
            Marshal.Copy(pData, m_data, 0, m_data.Length);

            //swap address
            m_dataStruct.m_address = Util.Swap(m_dataStruct.m_address);
         }
         catch (Exception)
         {
            throw;
         }
      }
      #endregion

      #region PublicFunctions
      /// <summary>
      /// Copy constructor
      /// </summary>
      /// <param name="rhs">The object to copy</param>
      public FPGAReadRegisterCmdBlockIncrMessage(FPGAReadRegisterCmdBlockIncrMessage rhs)
         : base(rhs)
      {
         try
         {
            m_dataStruct = rhs.m_dataStruct;
            m_byteSwap = rhs.m_byteSwap;
            m_data = rhs.m_data;
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// The constructor for sending
      /// </summary>
      /// <param name="page">The page to read from</param>
      /// <param name="address">The address to read</param>
      public FPGAReadRegisterCmdBlockIncrMessage(Page page, uint address, uint numWords, bool swapDataBytes)
         : base(FPGACmdMsgIds.TYPE_THREE_READ_CMD_ID, page, "Read Register Command")
      {
         try
         {
            m_dataStruct.m_address = address;
            m_byteSwap = swapDataBytes;

            //Create an empty array the size of numWords
            m_data = new byte[numWords * sizeof(uint)];
         }
         catch (Exception)
         {
            throw;
         }
      }

      /// <summary>
      /// Convert this object into string form
      /// </summary>
      /// <returns>A string representing this message</returns>
      public override String ToString()
      {
         string msg = base.ToString();
         msg += "   address: " + m_dataStruct.m_address.ToString() + "\r\n\r\n";
         return msg;
      }
      #endregion  
   }
}
