/****************************************************************************/
/* Copyright (c) 2000 MBARI                                                 */
/* MBARI Proprietary Information. All rights reserved.                      */
/****************************************************************************/
/* Summary  :                                                               */
/* Filename : DataLogWriter.cc                                              */
/* Author   :                                                               */
/* Project  :                                                               */
/* Version  : 1.0                                                           */
/* Created  : 02/07/2000                                                    */
/* Modified :                                                               */
/* Archived :                                                               */
/****************************************************************************/
/* Modification History:                                                    */
/****************************************************************************/
#include <stdlib.h>
#include <unistd.h>
#include <malloc.h>
#include <string.h>
#include <time.h>
#include "DataLogWriter.h"
#include "Syslog.h"
#include "ourTypes.h"
#include "Exception.h"
#include "BinaryFile.h"
#include "AsciiFile.h"


DataLogWriter::DataLogWriter(const char *objectName, 
			     DataLog::FileFormat fileFormat,
			     Boolean autoTimestamp)
  : DataLog(objectName, DataLog::Write, fileFormat),
    _timeStamp(TimeTagFieldName)
{
  _autoTimestamp = autoTimestamp;

  addField(&_timeStamp);

  //////////////////////////////////////////////////////////////////
  // Build file name and open the file
  char *auvLogDir = getenv(AuvLogDirName);

  if (auvLogDir == 0) {

    Syslog::write("DataLog::DataLog() - environment variable %s not set\n",
		  AuvLogDirName);
    exit(1);
  }

  sprintf(_fileName, "%s/%s/%s.log", auvLogDir, LatestLogDirName, name());

  openFile();

  switch (fileFormat) {

  case AsciiFormat:
    _logFile = new AsciiFile(fileStream());
    break;

  case BinaryFormat:
    _logFile = new BinaryFile(fileStream());
    break;

  default:
    Syslog::write("DataLogWriter::DataLogWriter() - unknown file format");
    exit(1);
  }
}


DataLogWriter::~DataLogWriter()
{
}


void DataLogWriter::addField(DataField *field)
{
  // Check for spaces in name
  if (strchr(field->name(), ' ') || strchr(field->name(), '\t')) {
    // Spaces not allowed in field name
    char errorBuf[100];
    sprintf(errorBuf, 
	    "Illegal field name: \"%s\"; whitespace not allowed in name",
	    field->name());

    throw Exception(errorBuf); 
  }

  fields.add(&field);
}


void DataLogWriter::writeHeader()
{
  Boolean debug = False;

  dprintf("DataLogWriter::writeHeader()");

  char buffer[256];

  switch (_fileFormat) {

  case BinaryFormat:
    fprintf(fileStream(), "%s %s %s\n", 
	    CommentChar, BinaryFormatMnem, mnemonic());
    break;

  case AsciiFormat:
    fprintf(fileStream(), "%s %s %s\n", CommentChar, AsciiFormatMnem, name());
    break;

  default:
    Syslog::write("DataLogWriter::writeHeader() - unknown format!");
    exit(1);
  }

  DataField *field;

  for (int i = 0; i < nFields(); i++) {

    fields.get(i, &field);

    // Print field type, name, and preferred ascii print format
    fprintf(fileStream(), "%s %s %s %s\n", 
	    CommentChar, field->typeMnemonic(), field->name(), 
	    field->asciiFormat());
  }

  fprintf(fileStream(), "%s %s\n", CommentChar, BeginDataMnem);

  _handledHeader = True;

  dprintf("DataLogWriter::writeHeader() - done");
}


int DataLogWriter::write()
{
  Boolean debug = False;

  if (!_handledHeader) {
    // Need to write header. Note that write() is not called until
    // after all Data fields have been added.
    writeHeader();
  }

  dprintf("DataLogWriter::write() - call setFields()");

  if (_autoTimestamp) {
    struct timespec timeSpec;
    clock_gettime(CLOCK_REALTIME, &timeSpec);
    _timeStamp.setValue((double )(timeSpec.tv_sec + timeSpec.tv_nsec/1.e9));
  }

  // Call subclass-defined method to set field values
  setFields();

  DataField *field;

  // Write each field value to logfile
  for (int i = 0; i < nFields(); i++) {

    fields.get(i, &field);

    field->write(_logFile);
  }

  dprintf("DataLogWriter::write() - done with each field");

  // Terminate this record
  _logFile->endRecord();

  return 0;
}


TimeTag *DataLogWriter::timeStamp()
{
  return &_timeStamp;
}

