// file: $isip/class/sp/FeatureFile/ftrf_04.cc
// version: $Id: ftrf_04.cc 10597 2006-08-08 21:28:39Z ss754 $
//

// isip include files
//
#include "FeatureFile.h"

// method: write
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: a boolean value indicating status
//
// this method has the object write itself to an Sof file.
//
boolean FeatureFile::write(Sof& sof_a, long tag_a,
			   const String& name_a) const {

  // declare local variables
  //
  long obj_size;

  // check the type of the Sof file
  //
  if (sof_a.isText()) {
    obj_size = Sof::ANY_SIZE;
  }
  else {
    obj_size = sofSize();
  }
  
  // put the object into the sof file's index
  //
  if (!sof_a.put(name_a, tag_a, obj_size)) {
    return false;
  }
  
  // exit gracefully
  //
  return writeData(sof_a);
}

// method: writeData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) textual parameter name
//
// return: a boolean value indicating status
//
// this method has the object write itself, with specified name and
// tag, to an Sof file.
// 
boolean FeatureFile::writeData(Sof& sof_a, const String& pname_a) const {

  // write a start string if necessary
  //
  sof_a.writeLabelPrefix(pname_a);

  // write the configuration
  //
  if (!writeConfig(sof_a)) {
    return Error::handle(name(), L"writeData", Error::IO,
			 __FILE__, __LINE__, Error::WARNING);
  }
  
  // put an end string if necessary
  //
  sof_a.writeLabelSuffix(pname_a);

  // exit gracefully
  //
  return true;
}

// method: writeStart
//
// arguments:
//  const String& pname: (input) textual parameter name
//
// return: a boolean value indicating status
//
// this method is required to support partial writes.
// 
boolean FeatureFile::writeStart(const String& pname_a) {
  
  if (file_type_d == TEXT)
    in_sof_d.put(name(), tag_d, -1);
  else
    in_sof_d.put(name(), tag_d, sofSize());
  
  writeStart(in_sof_d, pname_a);

  // exit gracefully
  // 
  return true;
}

// method: writeStart
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) textual parameter name
//
// return: a boolean value indicating status
//
// this method is required to support partial writes.
// 
boolean FeatureFile::writeStart(Sof& sof_a, const String& pname_a) const {

  // write a start string if necessary
  //
  sof_a.writeLabelPrefix(pname_a);

  // write the configuration
  //
  if (!writeConfig(sof_a)) {
    return Error::handle(name(), L"writeStart", Error::IO,
			 __FILE__, __LINE__, Error::WARNING);
  }

  // exit gracefully
  //
  return true; 
}

// method: writeTerminate
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) textual parameter name
//
// return: a boolean value indicating status
//
// this method is required to support partial writes.
// 
boolean FeatureFile::writeTerminate(Sof& sof_a, const String& pname_a) const {

  if (data_type_d == ALGORITHM_DATA) {
    // create a temporary buffer
    //
    Vector<AlgorithmData> temp;

    // terminate writing
    //
    if (!temp.writeTerminate(sof_a, PARAM_DATA)) {
      return Error::handle(name(), L"writeTerminate", Error::IO,
			   __FILE__, __LINE__, Error::WARNING);
    }
  }
  else if (data_type_d == VECTOR_FLOAT) {
    // create a temporary buffer
    //
    Vector<VectorFloat> temp;

    // terminate writing
    //
    if (!temp.writeTerminate(sof_a, PARAM_DATA)) {
      return Error::handle(name(), L"writeTerminate", Error::IO,
			   __FILE__, __LINE__, Error::WARNING);
    }
  } 
  
  // put an end string if necessary
  //
  sof_a.writeLabelSuffix(pname_a);

  // exit gracefully
  //
  return true;
}

// method: sofSize
//
// arguments: none
//
// return: size of object
//
// this method returns the size of the object.
//
long FeatureFile::sofSize() const {
  
  // calculate the space for the data type, format, etc.
  //
  long bytes = 0;

  bytes += name_d.sofSize();
  bytes += FILE_TYPE_MAP.elementSofSize();
  bytes += FILE_FORMAT_MAP.elementSofSize();
  bytes += COMP_TYPE_MAP.elementSofSize();

  // add the space required for the number and type of features
  //
  bytes += amplitude_range_d.sofSize();
  bytes += num_channels_d.sofSize();
  bytes += id_d.sofSize();
  bytes += num_features_d.sofSize();
  bytes += DATA_TYPE_MAP.elementSofSize();
  bytes += AlgorithmData::CTYPE_MAP.elementSofSize();

  // add space for buffer information
  //
  bytes += tag_d.sofSize();
  bytes += block_size_d.sofSize();
  bytes += buf_size_d.sofSize();
  
  // add space for signal processing parameters
  //
  bytes += frame_duration_d.sofSize();
  bytes += sample_frequency_d.sofSize();
  
  // return the size
  //
  return bytes;
}

// method: writeConfig
//
// arguments:
//  Sof& sof: (input) sof file object
//
// return: a boolean value indicating status
//
// this method has the object write its configuration to the Sof
// file. it assumes that the Sof file is already positioned correctly.
// 
boolean FeatureFile::writeConfig(Sof& sof_a) const {

  // write the name, format, etc.
  //
  if (!name_d.writeData(sof_a, PARAM_NAME)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  FILE_TYPE_MAP.writeElementData(sof_a, PARAM_FILE_TYPE,
				 (ushort)file_type_d);
  FILE_FORMAT_MAP.writeElementData(sof_a, PARAM_FILE_FORMAT,
				   (ushort)file_format_d);

  COMP_TYPE_MAP.writeElementData(sof_a, PARAM_COMP_TYPE,
				 (ushort)compression_type_d);
  
  // write the information about the data format
  //
  amplitude_range_d.writeData(sof_a, PARAM_RANGE);

  if (!num_channels_d.writeData(sof_a, PARAM_NUM_CHANNELS)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  if (!id_d.writeData(sof_a, PARAM_ID)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  num_features_d.writeData(sof_a, PARAM_NUM_FEATURES);

  if (!DATA_TYPE_MAP.writeElementData(sof_a,
				      PARAM_DATA_TYPE, (long)data_type_d)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  if (!AlgorithmData::CTYPE_MAP.writeElementData(sof_a, PARAM_COEF_TYPE,
					       (long)coef_type_d)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }
  
  // write the information about the buffer sizes
  //
  tag_d.writeData(sof_a, PARAM_TAG);
  block_size_d.writeData(sof_a, PARAM_BLOCK_SIZE);
  buf_size_d.writeData(sof_a, PARAM_BUF_SIZE);

  // write the signal processing parameters
  //
  if (!frame_duration_d.writeData(sof_a, PARAM_FRAME_DURATION)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  if (!sample_frequency_d.writeData(sof_a, PARAM_SAMPLE_FREQUENCY)) {
    return Error::handle(name(), L"writeConfig", Error::IO,
			 __FILE__, __LINE__);
  }

  // exit gracefully
  //
  return true;
}
