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

// isip include files
//
#include "FeatureFile.h"
#include <Filename.h>

// method: open
//
// arguments:
//  const Filename& filename: (input) file to open
//  File::MODE mode: (input) open mode
//
// return: a boolean value indicating status
//
// open the file.
//
boolean FeatureFile::open(const Filename& filename_a, File::MODE mode_a) {
      
  // mode: READ_ONLY
  //
  if (mode_a == File::READ_ONLY) {

    // reset the number of frames
    //
    num_frames_d = DEF_NUM_FRAMES;
  
    // check the type
    //
    File::TYPE type = File::BINARY;

    if (file_type_d == TEXT) {
      type = File::TEXT;
    }

    // format: SOF
    //
    if (file_format_d == SOF) {

      // open the sof file
      //
      if (!in_sof_d.open(filename_a, mode_a, type)) {
	return Error::handle(name(), L"open",
			     Error::ARG, __FILE__, __LINE__);
      }

      // read the sof file
      //
      if (!readSofStart()) {
	return Error::handle(name(), L"open", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
      }
    }

    // format: RAW
    //
    else if (file_format_d == RAW) {

      // call the master function in the File class
      //
      if (!raw_features_d.open(filename_a, mode_a, type)) {
	return Error::handle(name(), L"open", Error::IO, __FILE__, __LINE__,
			     Error::WARNING);
      }
	
      if (num_channels_d == (Long)0) {
	return Error::handle(name(), L"open", ERR, __FILE__, __LINE__);
      }
	
      // get the file basename as the id
      //
      filename_a.getBase(id_d);
    }
    
    // bad enumeration value
    //
    else {
      
      return Error::handle(name(), L"open", Error::ENUM, __FILE__, __LINE__);
    }
    
    // exit gracefully
    //
    return true;    
  }
  
  // check if the file exists
  //
  if (!File::exists(filename_a)) {
      
    // the file doesn't need to exist if we are in write only mode
    //
    if (mode_a == File::WRITE_ONLY) {

      // check for valid data
      //
      if (num_channels_d == (Long)0) {
	return Error::handle(name(), L"open", ERR, __FILE__, __LINE__);
      }

      // check the type and format
      //
      File::TYPE type = File::BINARY;

      if (file_type_d == TEXT) {
	type = File::TEXT;
      }
      
      // branch on format: RAW
      //
      if (file_format_d == RAW) {

	// call the master function in the File class
	//
	if (!raw_features_d.open(filename_a, mode_a, type)) {
	  return Error::handle(name(), L"open", Error::IO, __FILE__,
			       __LINE__, Error::WARNING);
	}
      }

      // format: SOF
      //
      else if (file_format_d == SOF) {
	if (!in_sof_d.open(filename_a, mode_a, type)) {
	  return Error::handle(name(), L"open", Error::ARG, __FILE__,
			       __LINE__);
	}
	
        if (!writeSofStart()) {
          return Error::handle(name(), L"open", Error::WRITE,
                               __FILE__, __LINE__, Error::WARNING);
        }
	
      }
      
      // else: unknown format
      //
      else {
	return Error::handle(name(), L"open", Error::ENUM,
			     __FILE__, __LINE__);
      }
    }
    
    // file does not exist but should, error
    //
    else {
      return Error::handle(name(), L"open", Error::FILE_NOTFND,
			   __FILE__, __LINE__, Error::WARNING);
    }
  }
  
  // else read existing file
  //
  else {

    // reset the number of frames
    //
    num_frames_d = DEF_NUM_FRAMES;    
    
    // check the type
    //
    File::TYPE type = File::BINARY;

    if (file_type_d == TEXT) {
      type = File::TEXT;
    }
    
    // is this an Sof file?
    //
    if (file_format_d == SOF) {
      if (!in_sof_d.open(filename_a, mode_a, type)) {
	return Error::handle(name(), L"open",
			     Error::ARG, __FILE__, __LINE__);
      }

      // start the partial read or write
      //
      if (mode_a == File::READ_ONLY) {
	if (!readSofStart()) {
	  return Error::handle(name(), L"open", Error::READ,
			       __FILE__, __LINE__, Error::WARNING);
	}	
      }
      else if (mode_a == File::WRITE_ONLY) {
	if (!writeSofStart()) {
	  return Error::handle(name(), L"open", Error::WRITE,
			       __FILE__, __LINE__, Error::WARNING);
	}
      }

      // bad enumeration value
      //
      else {
	return Error::handle(name(), L"open", Error::ENUM, __FILE__,
			     __LINE__);
      }
    }
    
    // else: RAW file
    //
    else if (file_format_d == RAW) {

      // check type
      //
      File::TYPE type = File::BINARY;

      if (file_type_d == TEXT) {
	type = File::TEXT;
      }

      // call the master function in the File class
      //
      if (!raw_features_d.open(filename_a, mode_a, type)) {
	return Error::handle(name(), L"open", Error::IO, __FILE__, __LINE__,
			     Error::WARNING);
      }
	
      if (num_channels_d == (Long)0) {
	return Error::handle(name(), L"open", ERR, __FILE__, __LINE__);
      }
	
      // get the file basename as the id
      //
      filename_a.getBase(id_d);
    }
    
    // bad enumeration value
    //
    else {
      return Error::handle(name(), L"open", Error::ENUM, __FILE__, __LINE__);
    }
  }
  
  // exit gracefully
  //
  return true;
}


// method: open
//
// arguments:
//  const unichar* filename: (input) file to open
//  File::MODE mode: (input) open mode
//
// return: a boolean value indicating status
//
// open the file.
//
boolean FeatureFile::open(const unichar* filename_a, File::MODE mode_a) {

  // declare local variables
  //
  Filename temp(filename_a);

  // call the master function
  //
  return open(temp, mode_a);
}

// method: close
//
// arguments:
//
// return: a boolean value indicating status
//
// close the file.
//
boolean FeatureFile::close() {

  // clear the id
  //
  id_d.clear();

  // branch on format: RAW
  //
  if (file_format_d == RAW) {
    return raw_features_d.close();
  }

  // format: SOF
  //
  else if (file_format_d == SOF) {

    if (data_type_d == ALGORITHM_DATA) {
      
      // create a buffer
      //
      Vector <AlgorithmData> buffer;
      
      // read data
      //
      if (in_sof_d.getPartialRead()) {
	buffer.readTerminate(in_sof_d);
      }
      
      // write data
      //
      else if (in_sof_d.getPartialWrite()) {
	buffer.writeTerminate(in_sof_d, PARAM_DATA);
      }
    }
    
    else if (data_type_d == VECTOR_FLOAT) {
      
      // create a buffer
      //
      Vector <VectorFloat> buffer;
      
      // read data
      //
      if (in_sof_d.getPartialRead()) {
	buffer.readTerminate(in_sof_d);
      }
      
      // write data
      //
      else if (in_sof_d.getPartialWrite()) {
	buffer.writeTerminate(in_sof_d, PARAM_DATA);
      }
    }
    
    // exit
    //
    return in_sof_d.close();
  }

  // enum error
  //
  else {
    return Error::handle(name(), L"close", Error::ENUM, __FILE__, __LINE__);
  }

  // exit gracefully
  //
  return true;
}

// method: resetBuffer
//
// arguments:
//  long ctag: (input) channel to clear
//
// return: a boolean value indicating status
//
// clear the circular buffer.
//
boolean FeatureFile::resetBuffer(long ctag_a) {

  // process all channels
  //
  if (ctag_a < 0) {

    // loop over all channels
    //
    for (long i = 0; i < num_channels_d; i++) {
      resetBuffer(i);
    }

    // exit gracefully
    //
    return true;
  }

  // clear the buffer
  //
  buffers_d(ctag_a).clear(Integral::RESET);

  // reset time index
  //
  buf_end_ftr_d(ctag_a) = -1;

  end_of_file_d = false;
  
  // exit gracefully
  //
  return true;
}

// method: isOpen
//
// arguments: none
//
// return: boolean answer
//
// this method determines if the file is already open.
//
boolean FeatureFile::isOpen() const {
  
  // branch on file type
  //
  if (file_format_d == RAW) {
    return raw_features_d.isOpen();
  }
  else if (file_format_d == SOF) {
    return in_sof_d.isOpen();
  }

  // enum error
  //
  else {
    return Error::handle(name(), L"isOpen", Error::ENUM, __FILE__, __LINE__);
  }

  // must not be open
  //
  return false;
}
