//=========================================================================
// Summary  : */
// Filename : ExternalMessage.h
// Author   : */
// Project  : */
// Revision : 1
// Created  : 2000/08/19
// Modified : 2000/08/19
//=========================================================================
// Description :
//=========================================================================
#ifndef _EXTERNALMESSAGE_H
#define _EXTERNALMESSAGE_H

#include <sys/types.h>
#include "Exception.h"

/*
CLASS 
ExternalMessage

DESCRIPTION
Encapsulates message data which is passed between onboard and
offboard processes.

In this implementation, external data is stored as ASCII representations
within a protected buffer.

AUTHOR
Tom O'Reilly
*/

class ExternalMessage {

public:

  class TokenNotFound : public Exception {

  public:

    TokenNotFound(unsigned theTokenNo) : Exception("Token not found") {
      tokenNo = theTokenNo;
    }

    unsigned tokenNo;
  };

  ExternalMessage(size_t maxBytes = 1024);
  ~ExternalMessage();

  ///////////////////////////////////////////////////////////////////
  enum MessageCode {
    ListTasks = 1000,
    InvokeTaskMethod,
    UnknownCode = 9999
  };

  ///////////////////////////////////////////////////////////////////
  // Type of message
  MessageCode messageCode();

  ///////////////////////////////////////////////////////////////////
  // Read message from socket into internal buffer
  int read(int socket);

  ///////////////////////////////////////////////////////////////////
  // Write message from internal buffer to socket
  int write(int socket, int nBytes);

  void addToken(const char *token);

protected:

  ///////////////////////////////////////////////////////////////////
  // Set messge code
  void setMessageCode(MessageCode code);

  ///////////////////////////////////////////////////////////////////
  // Get specified token
  const char *token(unsigned tokenNo);

  char *_buffer;
  char *_buffer2;
  size_t _bufferSize;

  static const char *_delimiter;

  enum ByteOffset {
    MessageCodeOffset = 0
  };


  int addField(size_t length);

  // Describe field position and length within buffer
  struct Field {

    // Length of field
    int nBytes;
  };

private:

  MessageCode _messageCode;
  static const char *_messageCodeFormat;

};


/*
CLASS 
ExternalMethodMessage

DESCRIPTION
Subclass of ExternalMessage; specifies method to be invoked

AUTHOR
Tom O'Reilly
*/
class ExternalMethodMessage : public ExternalMessage {

public:

  ExternalMethodMessage(size_t maxBytes);
  ~ExternalMethodMessage();

  ///////////////////////////////////////////////////////////////////
  // Destination task index.
  int taskIndex();

  ///////////////////////////////////////////////////////////////////
  // Request code
  int requestCode();

  ///////////////////////////////////////////////////////////////////
  // Number of bytes to send/receive
  size_t size();

protected:

  // Token count from beginning of ExternalMessage
  enum {
    TaskIndexToken = 1,
    RequestCodeToken,
    EventCodeToken
  };

};


/*
CLASS 
SubscriptionMessage

DESCRIPTION
Subclass of ExternalMessage; external subscription request

AUTHOR
Tom O'Reilly
*/
class SubscriptionMessage : public ExternalMethodMessage {

public:

  SubscriptionMessage(size_t maxBytes);
  ~SubscriptionMessage();

  int eventCode();

protected:

};

#endif

