// file: $isip/class/asr/AudioDatabase/audb_05.cc
// version: $Id: audb_05.cc 9382 2004-01-05 21:04:27Z alphonso $
//

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

// method: getRecord
//
// arguments:
//   String& identifier: (input) annotation graph id
//   Filename& filename: (output) desired annotation graph
//
// return: logical error status
//
// this method retrieves the record from the database
//
boolean AudioDatabase::getRecord(String& identifier_a, Filename& filename_a) {

  // declare local variables
  //
  Long* tag = (Long*)NULL;

  // trim whitespace characters
  //
  identifier_a.trim();

  if (identifier_a.eq(L"")) {
    return Error::handle(name(), L"getRecord - identifier is an empty string", Error::ARG, __FILE__, __LINE__);
  }

  // determine if the identifier exists in the database
  //  
  tag = hash_d.get(identifier_a);
  
  if (tag == (Long*)NULL) {
    return false;
  }
  
  // when the identifier exists in the database return a copy of the record
  //
  else {

    if (!filename_a.read(database_sof_d, (long)*tag)) {
      Error::handle(name(), L"getRecord", Error::NO_PARAM_FILE,
		    __FILE__, __LINE__);      
    }
  }

  // exit gracefully
  //
  return true;  
}

// method: assign
//
// arguments:
//  const AudioDatabase& arg
//
// return: logical error status
//
// this method has assigns the input AudioDatabase object
//
boolean AudioDatabase::assign(const AudioDatabase& arg_a) {

  // declare local variables
  //
  boolean status = false;

  // assign the member data
  //
  status = name_d.assign(arg_a.name_d);
  status &= hash_d.assign(arg_a.hash_d);  

  // return the status
  //
  return status;
}

// method: eq
//
// arguments:
//  const AudioDatabase& arg
//
// return: logical error status
//
// this method has determines if the AudioDatabase objects are equal
//
boolean AudioDatabase::eq(const AudioDatabase& arg_a) const {
  
  // declare local variables
  //
  boolean status = false;
  
  // determine if the objects are equal
  //
  status = name_d.eq(arg_a.name_d);
  status &= hash_d.eq(arg_a.hash_d);
  
  // return the status
  //
  return status;
}

// method: clear
//
// arguments:
//   Integral::CMODE cmode: (input) clear mode
//
// return: logical error status
//
// this method clears the content of the current object
//
boolean AudioDatabase::clear(Integral::CMODE cmode_a) {
  
  // declare local variables
  //
  boolean status = false;

  // clear the data members
  //  
  status = name_d.clear(cmode_a);
  status &= hash_d.clear(cmode_a);
  
  // return the status
  //
  return status;
}

// method: load
//
// arguments:
//  Sdb& sdb: (input) sdb file list Filename
//  Filename& file_list: (input) audio file list corresponding to above ID
//                     list, one line per file
//
// return: logical error status
//
// this method has assigns the input transcription database
//
boolean AudioDatabase::load(Sdb& id_a, Sdb& file_list_a,
			    Vector<Filename>& file_vec_a) {

  // loop from start
  //
  if (!id_a.gotoFirst()) {
    String msg(L"Error: no input file specified ");
    Console::put(msg);
    Error::handle(name(), L"load", Error::NO_PARAM_FILE,
                  __FILE__, __LINE__);
  }

  if (!file_list_a.gotoFirst()) {
    String msg(L"Error: no input file specified ");
    Console::put(msg);
    Error::handle(name(), L"load", Error::NO_PARAM_FILE,
                  __FILE__, __LINE__);
  }
  
  Filename id;
  Filename file_name;
    
  Long num_file = 0;

  // read the transcription file
  //
  do {

    // get id and corresponding file name
    //
    id_a.getName(id);
    file_vec_a.setLength((long)num_file + 1);
    file_list_a.getName(file_vec_a(num_file));

    // test the insert method
    //
    if (!insertRecord((String&)id, num_file)) {
      return Error::handle(name(), L"load", Error::TEST, __FILE__, __LINE__);
    }
    
    // move one forward for file count
    //
    num_file++;

  } while (id_a.gotoNext() && file_list_a.gotoNext());
  
  return true;
}

// method: load
//
// arguments:
//  Filename& file_list: (input) audio file list
//  Vector<Filename>& file_vec: (output) vector containing audio files
//
// return: a boolean value indicating status
//
// this method loads the audio database
//
boolean AudioDatabase::load(Filename& file_list_a,
			    Vector<Filename>& file_vec_a) {

  // local variables
  //
  boolean status = true;
  Long num_file = 0;
  String line;
  File audio_file;

  // debugging message
  //
  if (debug_level_d >= Integral::BRIEF) {
    Console::increaseIndention();
    String output;
    output.assign(L"\nloading input audio file: ");
    output.concat(file_list_a);
    Console::put(output);
    Console::decreaseIndention();
  }

  // open the audio list file
  //
  if (!audio_file.open(file_list_a, File::READ_ONLY)) {
    String msg(L"Error: no input audio file specified ");
    Console::put(msg);
    Error::handle(name(), L"load", Error::ERR,
                  __FILE__, __LINE__);
  }

  // read the audio list file line by line
  //
  while (audio_file.get(line)) {

    // local variables
    //
    long pos = 0;
    String id;
    Filename file_name;

    // get the number of fields (identifier and filename or just the
    // filename)
    //
    long num_tokens = 0;
    num_tokens = line.countTokens();    

    // skip any blank line
    //
    if (num_tokens == (long)0)
      continue;
    
    // parse the filename and derive the identifier as the line position
    // the format is : filename
    //
    if (num_tokens == (long)1) {
      line.tokenize(file_name, pos);
      id.assign(num_file);
    }
    
    // else parse the filename and the identifier
    // the format is: filename identifier
    //
    else if (num_tokens == (long)2) {
      line.tokenize(file_name, pos);
      line.tokenize(id, pos);
    }
    
    // else error
    //
    else if (num_tokens > (long)2) {
      String msg(L"Error: check the audio file format: filename [identifier]");
      Console::put(msg);
      Error::handle(name(), L"load", Error::ERR,
		    __FILE__, __LINE__);
    }
    
    // add the filename to the output filename vector
    //
    file_vec_a.setLength(num_file + (long)1);
    file_vec_a((long)num_file).assign(file_name);

    // insert the record in the database
    //
    if (!insertRecord((String&)id, num_file)) {
      return Error::handle(name(), L"load", Error::TEST, __FILE__, __LINE__);
    }
    
    // increment the file count
    //
    num_file++;

    // debugging message
    //
    if (debug_level_d >= Integral::BRIEF) {
      Console::increaseIndention();
      String output;
      output.assign(L"number of the file processed: ");
      output.concat(num_file);
      output.concat(L"\nidentifier: ");
      output.concat(id);
      output.concat(L"\naudio feature file: ");
      output.concat(file_name);
      Console::put(output);
      Console::decreaseIndention();
    }    
  }
  
  // debugging message
  //
  if (debug_level_d >= Integral::NONE) {
      Console::increaseIndention();
      String output;
      output.assign(L"total number of file processed: ");
      output.concat(num_file);
      Console::put(output);
      Console::decreaseIndention();
  }    
  
  // close the input audio file
  //
  audio_file.close();

  // exit gracefully
  //
  return status;
}

// method: store
//
// arguments:
//  Sdb& db_sof: (input) sof file
//  long tag: (input) tag for the database object
//  Vector<Filename>& file_vec: (input) vector containing audio files
//
// return:  a boolean value indicating status
//
// this method store the audio database to the sof file
//
boolean AudioDatabase::store(Sof& db_sof_a, long tag_a,
			     Vector<Filename>& file_vec_a) {
  
  // write audio database data
  //
  write(db_sof_a, tag_a);
  
  // write the file name vector
  //
  long len = file_vec_a.length();
  
  for (long i = 0; i < len; i++) {
    file_vec_a(i).write(db_sof_a, i);
  }

  // exit gracefully
  //
  return true;
}
