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

DataLogReader::DataLogReader(const char *fileName)
  : DataLog("datalog", DataLog::Read, DataLog::UnknownFormat)
{
  strcpy(_fileName, fileName);
  openFile();
  readHeader();
}


DataLogReader::~DataLogReader()
{
}


void DataLogReader::readHeader()
{
  char typeMnem[256];
  char buffer[256];
  char buffer2[256];
  char errorBuf[256];
  char *token;
  int nTokens;
  DataField *field;
  Boolean parseError = False;

  enum ParseState {
    ReadFormat, ReadDataFields
  };

  ParseState state = ReadFormat;

  parseError = False;

  while (!_handledHeader && !parseError) {

    // Read a line
    fgets(buffer, sizeof(buffer), fileStream());

    if (buffer[strlen(buffer)-1] == '\n') 
      // Strip off trailing newlien
      buffer[strlen(buffer)-1] = '\0';

    strcpy(buffer2, buffer);

    token = strtok(buffer, " ");

    if (token == 0) 
      // Blank line; skip it
      continue;

    if (strcmp(token, CommentChar)) {
      // Each header line should have leading comment character
      parseError = True;
      continue;
    }

    switch (state) {
      
    case ReadFormat:

      // Read file format mnemonic
      token = strtok(0, " ");
      if (token == 0) {
	// No token? Parse error
	parseError = True;
	continue;
      }

      if (!strcmp(token, AsciiFormatMnem)) {
	_fileFormat = AsciiFormat;
	_logFile = new AsciiFile(fileStream());
      }
      else if (!strcmp(token, BinaryFormatMnem)) {
	_fileFormat = BinaryFormat;
	_logFile = new BinaryFile(fileStream());
      }
      else {
	_fileFormat = UnknownFormat;
	sprintf(errorBuf, 
		"DataLogReader::readHeader() - Unknown file format \"%s\"",
		token);

	throw Exception(errorBuf);
      }

      // Read object name
      token = strtok(0, " ");
      if (token == 0) {
	// No token? Parse error
	parseError = True;
	continue;
      }
      setName(token);
      setMnemonic(token);

      // Start reading DataFields
      state = ReadDataFields;
      break;

    case ReadDataFields:

      nTokens = 0;

      while (!_handledHeader && (token = strtok(0, " ")) != 0) {

	switch (nTokens) {

	case 0:

	  // DataField type

	  if (!strcmp(token, BeginDataMnem)) {
	    // Done with header
	    _handledHeader = True;
	    continue;
	  }
	  strcpy(typeMnem, token);
	  
	  break;

	case 1:

	  // DataField name

	  field = 
	    DataFieldFactory::instanceOf()->create(typeMnem, token);

	  if (field == 0) {
	    sprintf(errorBuf,
		    "DataLogReader::readHeader() - "
		    "unknown DataField type \"%s\"", typeMnem);

	    throw Exception(errorBuf);
	  }
	  else
	    fields.add(&field);

	  break;

	case 2:
	  // Optional preferred printing format
	  field->setAsciiFormat(token);
	  break;


	default:

	  parseError = True;
	}
	nTokens++;
      }

      if (!_handledHeader && nTokens != 2 && nTokens != 3) {
	parseError = True;
      }
    }
  }

  if (parseError) {
    sprintf(errorBuf, "DataLogReader::readHeader() - "
	    "Error parsing \"%s\"", buffer2);

    throw Exception(errorBuf);
  }

  _handledHeader = True;
}



int DataLogReader::read()
{
  DataField *field;

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

    fields.get(i, &field);

    field->read(_logFile);
  }

  return 0;
}



void DataLogReader::print()
{
  Boolean debug = True;

  DataField *field;
  int i;

  printf("# ");
  for (i = 0; i < fields.size(); i++) {
    fields.get(i, &field);
    printf("%s ", field->name());
  }
  printf("\n");

  try {
    while (True) {

      // Read a record
      read();

      for (i = 0; i < fields.size(); i++) {
	fields.get(i, &field);

	fprintf(stdout, "%s   ", field->ascii());
      }

      fprintf(stdout, "\n");
    }
  }
  catch (Exception e) {
    dprintf("DataLogReader::read() - %s", e.msg);
    return;
  }
}




