// **********************************************************************************************************
//    AutomationMessageHeader.cs
//    1/8/2024
//    NGI - Next Generation Interceptor
//    
//    Contract No. HQ0856-21-C-0003/1022000209
//    
//    THIS DOCUMENT DOES NOT CONTAIN TECHNOLOGY OR TECHNICAL DATA CONTROLLED UNDER EITHER THE U.S. 
//    INTERNATIONAL TRAFFIC IN ARMS REGULATIONS OR THE U.S. EXPORT ADMINISTRATION REGULATIONS.
//    
//    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.
//    
//    UNPUBLISHED WORK - COPYRIGHT RAYTHEON COMPANY.
//    
//    DESTRUCTION NOTICE: FOR CLASSIFIED DOCUMENTS FOLLOW THE PROCEDURES IN DOD 5220.22-M, 
//    NATIONAL INDUSTRIAL SECURITY PROGRAM OPERATING MANUAL, FEBRUARY 2006, 
//    INCORPORATING CHANGE 1, MARCH 28, 2013, CHAPTER 5, SECTION 7, OR DODM 5200.01-VOLUME 3, 
//    DOD INFORMATION SECURITY PROGRAM: PROTECTION OF CLASSIFIED INFORMATION, ENCLOSURE 3, 
//    SECTION 17. FOR CONTROLLED UNCLASSIFIED INFORMATION FOLLOW THE PROCEDURES IN DODM 5200.01-VOLUME 4, 
//    INFORMATION SECURITY PROGRAM: CONTROLLED UNCLASSIFIED INFORMATION.
//    
//    CONTROLLED BY: MISSILE DEFENSE AGENCY
//    CONTROLLED BY: GROUND-BASED MIDCOURSE DEFENSE PROGRAM OFFICE
//    CUI CATEGORY: CTI 
//    DISTRIBUTION/DISSEMINATION CONTROL: F 
//    POC: Alex Kravchenko (1118268)
// **********************************************************************************************************
using System;
using System.Runtime.InteropServices;

namespace Raytheon.Common
{
	/// <summary>
	/// The header for all messages
	/// </summary>
	public class AutomationMessageHeader
	{
		#region PublicClassMembers
		public const int HEADER_EXPECTED_SIZE = 8;
		#endregion

		#region PrivateClassMembers
		[StructLayout(LayoutKind.Sequential, Pack = 1)]
		private struct HeaderStruct
		{
			public uint messageId;
			public uint messageLength;// total msg size in bytes..Including the header.
		};

		private HeaderStruct _headerStruct;
		#endregion

		#region PublicClassFunctions

		/// <summary>
		/// Copy constructor
		/// </summary>
		/// <param name="header">The header to copy</param>
		public AutomationMessageHeader(AutomationMessageHeader header)
		{
			_headerStruct = new HeaderStruct();
			_headerStruct = header._headerStruct;
		}

		/// <summary>
		/// Constructor for when receiving data.
		/// Use this constructor and then parse to populate it
		/// </summary>
		public AutomationMessageHeader()
		{
			_headerStruct = new HeaderStruct();
		}

		/// <summary>
		/// Constructor for sending
		/// </summary>
		/// <param name="msgId">the message id</param>
		/// <param name="messageLength">The number of bytes in the message, not including the header</param>
		public AutomationMessageHeader(uint msgId, uint messageLength)
		{
			_headerStruct = new HeaderStruct
			{
				messageId = msgId,
				messageLength = messageLength + GetHeaderLength()
			};
		}

		/// <summary>
		/// Encode the header into a byte array for sending
		/// </summary>
		/// <param name="pData">The buffer to put the message items</param>
		public void Format(IntPtr pData)
		{
			Marshal.StructureToPtr(_headerStruct, pData, true);
		}

		/// <summary>
		/// Getter
		/// </summary>
		/// <returns>The number of bytes in the message, including header</returns>
		public uint GetEntireMsgLength()
		{
			return _headerStruct.messageLength;
		}

		/// <summary>
		/// getter
		/// </summary>
		/// <returns>The id</returns>
		public uint GetMessageId()
		{
			return _headerStruct.messageId;
		}

		/// <summary>
		/// getter
		/// </summary>
		/// <returns>The header length in bytes</returns>
		public uint GetHeaderLength()
		{
			return (uint)Marshal.SizeOf(_headerStruct);
		}

		/// <summary>
		/// Takes an array of bytes and populates the header object
		/// </summary>
		/// <param name="pData">The header in byte form</param>
		public void Parse(IntPtr pData)
		{
			_headerStruct = (HeaderStruct)Marshal.PtrToStructure(pData, typeof(HeaderStruct));
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="messageLength"></param>
		public void SetMessageLen(uint messageLength)
		{
			_headerStruct.messageLength = messageLength + GetHeaderLength();
		}

		/// <summary>
		/// Creates a string version of the header members
		/// </summary>
		/// <returns>A string containing the header data</returns>
		public override string ToString()
		{
			string msg = "Header Data:\r\n";
			msg += "msg id: " + Convert.ToString(_headerStruct.messageId) + "\r\n";
			msg += "msg len: " + Convert.ToString(_headerStruct.messageLength) + "\r\n";
			return msg;
		}
		#endregion
	}
}
