/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : OffboardMessage.cc                                            */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <ctype.h>
#include <malloc.h>
#include <sys/uio.h>
#include <unistd.h>
#include "OffboardMessage.h"
#include "Exception.h"
#include "ourTypes.h"
#include "Syslog.h"
#include "CharData.h"
#include "ShortData.h"
#include "IntegerData.h"
#include "FloatData.h"
#include "DoubleData.h"

OffboardMessage::OffboardMessage(int nBufferBytes)
{
  char errorBuf[100];

  if ((_buffer = (char *)malloc(nBufferBytes)) == 0) {

    sprintf(errorBuf, 
	    "OffboardMessage::OffboardMessage() - malloc() failed (%d bytes)",
	    nBufferBytes);

    throw Exception(errorBuf);
  }
  _bufPtr = _buffer;
  _nBufferBytes = nBufferBytes;
  _endPtr = _buffer + _nBufferBytes;
}


OffboardMessage::~OffboardMessage()
{
}


void OffboardMessage::set(CharData *charData)
{
  sprintf(_tmpBuf, "%s ", charData->ascii());

  if (_bufPtr + strlen(_tmpBuf) >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  strcpy(_bufPtr, _tmpBuf);

  _bufPtr += strlen(_bufPtr);
}


void OffboardMessage::set(ShortData *shortData)
{
  sprintf(_tmpBuf, "%s ", shortData->ascii());

  if (_bufPtr + strlen(_tmpBuf) >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  strcpy(_bufPtr, _tmpBuf);

  _bufPtr += strlen(_bufPtr);
}


void OffboardMessage::set(IntegerData *integerData)
{
  sprintf(_tmpBuf, "%s ", integerData->ascii());

  if (_bufPtr + strlen(_tmpBuf) >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  strcpy(_bufPtr, _tmpBuf);

  _bufPtr += strlen(_bufPtr);
}


void OffboardMessage::set(FloatData *floatData)
{
  sprintf(_tmpBuf, "%s ", floatData->ascii());

  if (_bufPtr + strlen(_tmpBuf) >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  strcpy(_bufPtr, _tmpBuf);

  _bufPtr += strlen(_bufPtr);
}


void OffboardMessage::set(DoubleData *doubleData)
{
  sprintf(_tmpBuf, "%s ", doubleData->ascii());

  if (_bufPtr + strlen(_tmpBuf) >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  strcpy(_bufPtr, _tmpBuf);

  _bufPtr += strlen(_bufPtr);
}


void OffboardMessage::get(CharData *charData)
{
  charData->parseValue(nextToken());
}


void OffboardMessage::get(ShortData *shortData)
{
  shortData->parseValue(nextToken());
}


void OffboardMessage::get(IntegerData *integerData)
{
  integerData->parseValue(nextToken());
}


void OffboardMessage::get(FloatData *floatData)
{
  floatData->parseValue(nextToken());
}


void OffboardMessage::get(DoubleData *doubleData)
{
  doubleData->parseValue(nextToken());
}


void OffboardMessage::endRecord()
{
  if (_bufPtr + 1 >= _endPtr) 
    throw Exception("OffboardMessage::set(CharData) - buffer full");

  sprintf(_bufPtr, "\n");

  _bufPtr += strlen(_bufPtr);
}


char *OffboardMessage::nextToken()
{
  char *endOfToken;

  if (startNextToken(_bufPtr) == 0)
      throw Exception("OffboardMessage::nextToken() - end of buffer");

  // Find end of token
  for (endOfToken = _bufPtr + 1; 
       *endOfToken != '\0' && !isspace(*endOfToken) && *endOfToken != '\n';
       endOfToken++) {
    ;
  }

  strncpy(_tmpBuf, _bufPtr, endOfToken - _bufPtr);
  _tmpBuf[endOfToken - _bufPtr] = '\0';

  _bufPtr = endOfToken;

  return _tmpBuf;
}


char *OffboardMessage::startNextToken(char *buffer) 
{
  char *ptr;
  
  // Find first non-white character
  for (ptr = buffer; *ptr != '\0'; ptr++) {

    if (!isspace(*ptr))
      return ptr;
  }

  return 0;
}


void OffboardMessage::reset()
{
  memset(_buffer, 0, _nBufferBytes);

  _bufPtr = _buffer;
}



int OffboardMessage::nBufferSize()
{
  return _nBufferBytes;
}



int OffboardMessage::read(int socket)
{
  reset();

  // Fill buffer from socket
  int status = ::read(socket, _buffer, _nBufferBytes);

  if (status <= 0)
    return status;

  IntegerData integerData("int");

  // Read TaskInterface index
  integerData.read(this);
  _taskIndex = integerData.value();

  // Read method code
  integerData.read(this);
  _methodCode = integerData.value();

  return status;
}


int OffboardMessage::write(int socket)
{
  return ::write(socket, _buffer, _bufPtr - _buffer);
}


int OffboardMessage::taskIndex()
{
  return _taskIndex;
}


int OffboardMessage::methodCode()
{
  return _methodCode;
}


