//=========================================================================
// Summary  : Modem Message Enumerations.
// Filename : ModemMessage.h
// Author   : bluefinrobotics.com
// Project  : Remote Modem Message
// Revision : 1
// Created  : 2002
// Modified : 2003.03.11 Reed: added SeabirdSBE25.
//=========================================================================
// Description :  Remote Modem Message Enumerations.
//=========================================================================

#ifndef _MODEMMESSAGE_H
#define _MODEMMESSAGE_H

#include <string>
#include <ourTypes.h>
#include <Serialization.h>

// Maximum total length of a serialized ModemMessage
#define iMAX_MESSAGE_SIZE 1024

// Codes for pretending to be standard SharedObject-like guys
#define ModemMessageMsgCode 20
#define ModemMessageRequestMsgCode (ModemMessageMsgCode+1)

class MMConvertible;

//////////////////////////////////////////////////
//  Priority - an enum of possible priority values.
enum Priority
{
  pDEFAULT,    // no priority specified, use the config file default or AVERAGE
  pBEGIN,      // placeholder for loop iteration
  pOPTIONAL = pBEGIN,   // only send this data if you have plenty of bandwidth and power.
  pLOW,        // not important
  pAVERAGE,    // standard mission data
  pHIGH,       // important mission data
  pURGENT,      // safety data- danger messages only
  pMETA,        // transmission information, such as ACKs
  pEND        // placeholder for loop iteration
};


///////////////////////////////////////////////////////
//  A data holder for data that we want passed to a remote machine
//   via the modem.  Fairly generic.  Cannot pass between threads easily,
//   as the Message maintains pointers to locally allocated data.

class ModemMessage
{
 public:

  enum Type
  {
      // NEVER INSERT NEW TYPES ANYWHERE EXCEPT IMMEDIATELY BEFORE tEND!!!!!!!

    tUNKNOWN = 0,                           // we have no idea!
    tACK = 1,                               // acknowledgement of previous message
    tSTRING = 2,                            // human-readable string data
    tSYSTEM_COMMAND = 3,                    // command for remote system
    tMMNavigationPosition = 4,              //Navigation position message
    tMMNavigationPositionRequest = 5,       //Navigation position request message
    tMMNavigationAttitude = 6,              //Navigation state message
    tMMNavigationStateRequest = 7,          //Navigation state request message
    tMMAgentRequest = 8,	                //Turns on/off streaming data or gets single-shot
    tMMTailcone = 9,	                // Control tailcone and get feedback
    tMMCircuit = 10, 			// Power circuit status message
    tMMCircuitCurrent = 11,    	        // Power circuit current message
    tMMGroundFaultCurrent = 12,              // Ground fault current message
    tMMTemperature = 13, 		        // Power board temperature message
    tMMWaterAlarm = 14,			// Water alarm message
    tMMServerAlarm = 15,			// Server alarm message
    tMMDropWeightRelease = 16,               // Drop weight release message
    tMMDynamicControlCommand = 17,	        //Dynamic Control command message
    tMMDynamicControlCommandFull = 18,       //Full-fledge dynamic control message
    tMMWaterAlarmBatch = 19,		        //Array of water alarms
    tMMServerAlarmBatch = 20,	        //Array of server alarms
    tMMDropWeightReleaseBatch = 21,          //Array of drop weight release flags
    tMMCircuitBatch = 22,		        //Array of circuit on/off flags
    tMMCircuitCurrentBatch = 23,             //Array of circuit currents
    tMMGroundFaultCurrentBatch = 24,         //Array of ground fault currents
    tMMTemperatureBatch = 25,		//Array of sphere temperatures
    tMMDeviceInfo = 26,			//Uncompressed device info
    tMMTailconeRaw = 27, 			//Raw tailcone actuator readings
    tMMAhrs = 28,				//Attitude, heading roll sensor
    tMMDepthSensor = 29,			//Pressure depth sensor
    tMMWatchdog = 30,		        //Power board watchdogs
    tMMDvl = 31,				//DVL vx,vy,vz, and range
    tMMDvlBeamVelocities = 32,		//DVL beam velocities
    tMMDvlBeamRanges = 33,			//DVL beam ranges
    tMMHoming = 34,				//APOGEE homing message
    tMMGps = 35,				//Gps message type
    tMMString = 36,				//Generic string
    tMMNmea = 37,				//NMEA message type
    tMMAbortMission = 38,			//Abort mission message indicator
    tMMRtcm = 39,				//RTCM message
    tMMUSBLFix = 40,				//USBL fix messages
    tMMServer = 41,
    tMMMissionInfo = 42,
    tMMBehavior = 43,
    tMMBehaviorArray = 44,
    tMMActiveBehavior = 45,
    tMMMissionName = 46,
    tMMDriver = 47,
    tMMOas = 48,
    tMMSvs = 49,
    tMMDvlAttTemp = 50,
    tMMCircuitInfo = 51,
    tMMJumpBehavior = 52,
    tMMLN250 = 53,
    tMMBluefinBatteryInfo = 54,
    tMMBluefinBatteryGlobal = 55,
    tMMKillMission = 56,
    tMMLogDirName = 57,
    tMMControlExecute = 58,
    tMMMultiLeica = 59,
    tMMSeacat = 60,
    tMMSas21 = 61,
    tMMPhins = 62,
    tMMSeabirdSBE25 = 63,
    tMMEnvironmental = 64,
    tMMFluorometer = 65,

    //insert here
    tEND
  };

  enum ControlType   // Do we want to make sure that this guy gets through?
  {
    // NEVER INSERT NEW TYPES ANYWHERE EXCEPT IMMEDIATELY BEFORE ctEND!!!!!!!
    ctNoAck,      // Nope.  If it does not get through, that's okay.
    ctAck,        // Make sure that this guy gets through.  If you don't see an ACK
                  //  for him, send him again.  It's OK if the receiver gets him more
                  //  than once.
    ctExactlyOnce,// Like ctAck, but this guy cannot arrive more than once.
                  //  The receiver filters extras out.  This is somewhat expensive.
    ctEND
  };

  ModemMessage(const char* buffer);  // turns binary into true message form

  ModemMessage(const ModemMessage* pMessage);  // copy construction

  ModemMessage(const MMConvertible* pMMC);

  ~ModemMessage();

  //////////////////////////////////////////////////
  //  getBuffer - returns a pointer to the data in the message.
  const char* getBuffer() const
  { return _pcBuffer; };

  //////////////////////////////////////////////////
  //  getBufferWritable - returns a pointer to the data in the message.
  char* getBufferWritable()
  { return _pcBuffer; };

  //////////////////////////////////////////////////
  //  getBufferSize - returns length of the pointer in the message.
  int getBufferSize() const
  { return _iBufferLength; };


  //////////////////////////////////////////////////
  //  getType - returns the type of the message.
  Type getType() const
  { return _type; };

  //////////////////////////////////////////////////
  //
  //time_t tGetAbsoluteTimeout() const { return _tTimeout; }

  //////////////////////////////////////////////////
  //  pcUnparse - writes a binary version of the message into buffer,
  //   returns pointer to the byte after the last byte used in this way
  char *pcUnparse(char* buffer) const;

  //////////////////////////////////////////////////
  //  pcParse - reads a binary buffer as written by pcUnparse
  //   returns pointer to the byte after the last byte used in this way
  void pcParse(const char* buffer);

  //////////////////////////////////////////////////
  //  nBinaryBytes - number of bytes that would be written by pcUnparse
  int nBinaryBytes() const;

  //////////////////////////////////////////////////
  //  nActualBytes - number of bytes used up by the actual object
  int nActualBytes() const { return sizeof(ModemMessage)+_iBufferLength; };

  static int overhead() { return 2; }; // svelte, eh?


 protected:
  char* _pcBuffer;            // data buffer
  int _iBufferLength;         // length of data buffer in bytes
  Type _type;                 // what kind of message is this?

  //
  // Friends
  //
  friend class ModemBroker;
};


// Parent class for guys who can easily convert back and forth from ModemMessage.
class MMConvertible
{
public:
  // Should define a Child::Child(const ModemMessage*) constructor for each child.
  // Should define a copy constructor for each child.  If not, C++ may implement it
  //  by converting to ModemMessage and back again.  Copy is used in lots of hidden places.

  // Required serialization calls:
  virtual const char* pcRead(const char* sourceBuffer) = 0;
  virtual char *pcWrite(char * destBuffer) const = 0;

  // Required ModemMessage type ID.
  virtual ModemMessage::Type tGetMessageType() const = 0;

  // Optional default control
  virtual ModemMessage::ControlType ctGetDefaultControlType() const
  { return ModemMessage::ctNoAck; };

};

#endif
