/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : ExternalMessage.h                                             */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#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

