// **********************************************************************************************************
//    AutomationMessage.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;

namespace Raytheon.Common
{
   /// <summary>
   /// An abstract base class for AutomationMessages that go between the client and server
   /// </summary>
   public abstract class AutomationMessage : ICloneable
   {
      #region PrivateClassMembers
      private string _description;
      protected AutomationMessageHeader _header;
      #endregion

      #region PrivateClassFunctions

      /// <summary>
      /// The constructor
      /// </summary>
      /// <param name="AutomationMessageId">The AutomationMessage id</param>
      /// <param name="description">The AutomationMessage description</param>
      /// <param name="messageId">The number of bytes in the payload of the AutomationMessage. (The number of bytes in the child class)</param>
      protected AutomationMessage(uint messageId, string description, uint messageLength)
      {
         _description = description;
         _header = new AutomationMessageHeader(messageId, messageLength);
      }

      /// <summary>
      /// Copy Constructor
      /// </summary>
      /// <param name="message">The AutomationMessage to copy from</param>
      protected AutomationMessage(AutomationMessage message)
      {
         _header = new AutomationMessageHeader(message._header);
         _description = message._description;
      }



      /// <summary>
      /// Sets the number of bytes in the entire AutomationMessage, including header.
      /// Some times when receiving a AutomationMessage, you must instantiate the object before you know how many bytes the AutomationMessage is
      /// </summary>
      /// <param name="messageLength">The number of bytes in the entire AutomationMessage</param>
      protected void SetMessageLen(uint messageLength)
      {
         _header.SetMessageLen(messageLength);
      }

      /// <summary>
      /// abstract function for children to implement a clone of their object
      /// </summary>
      /// <returns></returns>
      protected abstract object CloneSelf();

      /// <summary>
      /// abstract function for children to implement the function that they serve
      /// </summary>
      public abstract void ExecuteMsg();

      /// <summary>
      /// abstract function for children to implement the formatting of their parameters
      /// </summary>
      /// <param name="pData"></param>
      protected abstract void FormatData(IntPtr pData);

      /// <summary>
      /// abstract function for children to implement the parsing of their parameters
      /// </summary>
      /// <param name="pData"></param>
      protected abstract void ParseData(IntPtr pData);
      #endregion

      #region PublicClassFunctions

      /// <summary>
      /// Get a copy of the AutomationMessage object
      /// </summary>
      /// <returns></returns>
      public object Clone()
      {
         // tell the child to clone itself
         return this.CloneSelf();
      }

      /// <summary>
      /// Encode the AutomationMessage into a byte array for sending
      /// </summary>
      /// <param name="pData">The buffer to put the AutomationMessage items</param>
      public void Format(IntPtr pData)
      {
         _header.Format(pData);

         IntPtr pPayload = IntPtr.Add(pData, (int)GetHeaderLength());

         // ask child class to format its data
         FormatData(pPayload);
      }

      /// <summary>
      /// Getter
      /// </summary>
      /// <returns>The description</returns>
      public string GetDescription()
      {
         return _description;
      }

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

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

      /// <summary>
      /// getter
      /// </summary>
      /// <returns>The number of bytes in the head</returns>
      public uint GetHeaderLength()
      {
         return _header.GetHeaderLength();
      }

      /// <summary>
      /// Takes an array of bytes and populates the AutomationMessage object
      /// </summary>
      /// <param name="pData">The AutomationMessage in byte form</param>
      public void Parse(IntPtr pData)
      {
         _header.Parse(pData);

         IntPtr pPayLoad = IntPtr.Add(pData, (int)GetHeaderLength());

         ParseData(pPayLoad);
      }

      /// <summary>
      /// Convert this AutomationMessage into string form
      /// </summary>
      /// <returns>The AutomationMessage in string form</returns>
      public override string ToString()
      {
         return "Description: " + GetDescription() + "\n" + _header.ToString();
      }
      #endregion
   }
}
