// file: $isip/class/stats/MixtureModel/mm_04.cc
// version: $Id: mm_04.cc 8756 2002-10-18 21:47:07Z alphonso $
//

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

// method: writeAccumulator
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: logical error status
//
// this method has the object write accumulators to an Sof file 
//
boolean MixtureModel::writeAccumulator(Sof& sof_a, long tag_a,
				 const String& name_a) const {

  // write the instance of the object into the Sof file
  //
  long obj_size = 0;
  
  if (sof_a.isText()) {

    // set the size to by dynamic
    //
    obj_size = Sof::ANY_SIZE;
  }
  else {

    // save the state of the list
    //
    const_cast<SingleLinkedList<StatisticalModel>& >(models_d).setMark();
    
    boolean end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoFirst());
    
    // loop through the list
    //
    while (!end_loop) {

      // get the size of the item
      //
      obj_size += const_cast<SingleLinkedList<StatisticalModel>& >(models_d).getCurr()->sofAccumulatorSize();
    
      // move to the next node
      //
      end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoNext());
    }

    // restore the state of the list
    //
    const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoMark();    
  }

  // write the object into the sof file's index
  //
  if (!sof_a.put(name_a, tag_a, obj_size)) {
    return false;
  }
  
  // now write the data
  //
  return writeAccumulatorData(sof_a);
}

// method: writeAccumulatorData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//
// return: logical error status
//
// this method has the object write itself to an Sof file. it assumes
// that the Sof file is already positioned correctly.
//
boolean MixtureModel::writeAccumulatorData(Sof& sof_a, const String& pname_a) const {

  // we need an empty string for the sub-parameter
  //
  String empty_str;
  String start_str;
  start_str.assign(SofParser::DEF_BLOCKSTART_CHAR);       // L"{"
  start_str.concat(SofParser::NEWLINE_CHAR);
  
  String end_str(SofParser::NEWLINE_CHAR);
  end_str.assign(SofParser::DEF_BLOCKSTOP_CHAR);          // L"}"

  String delim_str(end_str);
  delim_str.concat(SofParser::DEF_DELIMITER_CHAR);       
  delim_str.concat(SofParser::SPACE_CHAR);
  delim_str.concat(start_str);                           // L"}, {"
  
  String term;
  term.assign(SofParser::DEF_TERMINATOR_CHAR);
  term.concat(SofParser::NEWLINE_CHAR);                  // L";\n"

  String pname;
  pname.assign(PARAM_MODELS);                            // L"models"
  
  // if text, write a parameter name
  //
  if (sof_a.isText()) {
    
    if (pname.length() > 0) {
      String output;
      output.assign(pname);
      output.concat(SofParser::SPACE_CHAR);
      output.concat(SofParser::DEF_ASSIGNMENT_CHAR);
      output.concat(SofParser::SPACE_CHAR);
      sof_a.puts(output);
    }

    if ((long)models_d.length() > 0) {
      sof_a.puts(start_str);
    }
  }
  
  boolean is_first = true;

  // save the state of the list
  //
  const_cast<SingleLinkedList<StatisticalModel>& >(models_d).setMark();
  
  boolean end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoFirst());
  
  // loop through the list
  //
  while (!end_loop) {

    if (sof_a.isText()) {
      if (!is_first) {
	sof_a.decreaseIndention();
	sof_a.puts(delim_str);
      }
      sof_a.increaseIndention();
      is_first = false;
    }
    
    // write this element
    //
    if (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).getCurr()->writeAccumulatorData(sof_a, empty_str)) {
      return Error::handle(name(), L"writeAccumulatorData", Error::ARG, __FILE__, __LINE__);
    }

    // move to the next node
    //
    end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoNext());
  }

  // restore the state of the list
  //
  const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoMark();
   
  if (sof_a.isText()) {
    
    // write the close brace
    //
    if ((long)models_d.length() > 0) {
      sof_a.decreaseIndention();
      sof_a.puts(end_str);
    }
    
    // possibly terminate the statement
    //
    if (pname.length() > 0) {
      sof_a.puts(term);
    }
  }
  
  // exit gracefully
  //
  return true;  
}

// method: writeOccupancies
//
// arguments:
//  Sof& sof: (input) sof file object
//  long tag: (input) sof object instance tag
//  const String& name: (input) sof object instance name
//
// return: logical error status
//
// this method has the object write occupancies to an Sof file 
//
boolean MixtureModel::writeOccupancies(Sof& sof_a, long tag_a,
				 const String& name_a) const {

  // write the instance of the object into the Sof file
  //
  long obj_size = 0;
  
  if (sof_a.isText()) {

    // set the size to by dynamic
    //
    obj_size = Sof::ANY_SIZE;
  }
  else {

    // save the state of the list
    //
    const_cast<SingleLinkedList<StatisticalModel>& >(models_d).setMark();
    
    boolean end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoFirst());
    
    // loop through the list
    //
    while (!end_loop) {

      // get the size of the item
      //
      obj_size += const_cast<SingleLinkedList<StatisticalModel>& >(models_d).getCurr()->sofOccupanciesSize();
    
      // move to the next node
      //
      end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoNext());
    }

    // restore the state of the list
    //
    const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoMark();    
  }

  // write the object into the sof file's index
  //
  if (!sof_a.put(name_a, tag_a, obj_size)) {
    return false;
  }
  
  // now write the data
  //
  return writeOccupanciesData(sof_a);
}

// method: writeOccupanciesData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//
// return: logical error status
//
// this method has the object write itself to an Sof file. it assumes
// that the Sof file is already positioned correctly.
//
boolean MixtureModel::writeOccupanciesData(Sof& sof_a, const String& pname_a) const {

  // we need an empty string for the sub-parameter
  //
  String empty_str;
  String start_str;
  start_str.assign(SofParser::DEF_BLOCKSTART_CHAR);       // L"{"
  start_str.concat(SofParser::NEWLINE_CHAR);
  
  String end_str(SofParser::NEWLINE_CHAR);
  end_str.assign(SofParser::DEF_BLOCKSTOP_CHAR);          // L"}"

  String delim_str(end_str);
  delim_str.concat(SofParser::DEF_DELIMITER_CHAR);       
  delim_str.concat(SofParser::SPACE_CHAR);
  delim_str.concat(start_str);                           // L"}, {"
  
  String term;
  term.assign(SofParser::DEF_TERMINATOR_CHAR);
  term.concat(SofParser::NEWLINE_CHAR);                  // L";\n"

  String pname;
  pname.assign(PARAM_MODELS);                            // L"models"
  
  // if text, write a parameter name
  //
  if (sof_a.isText()) {
    
    if (pname.length() > 0) {
      String output;
      output.assign(pname);
      output.concat(SofParser::SPACE_CHAR);
      output.concat(SofParser::DEF_ASSIGNMENT_CHAR);
      output.concat(SofParser::SPACE_CHAR);
      sof_a.puts(output);
    }

    if ((long)models_d.length() > 0) {
      sof_a.puts(start_str);
    }
  }
  
  boolean is_first = true;

  // save the state of the list
  //
  const_cast<SingleLinkedList<StatisticalModel>& >(models_d).setMark();
  
  boolean end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoFirst());
  
  // loop through the list
  //
  while (!end_loop) {

    if (sof_a.isText()) {
      if (!is_first) {
	sof_a.decreaseIndention();
	sof_a.puts(delim_str);
      }
      sof_a.increaseIndention();
      is_first = false;
    }
    
    // write this element
    //
    if (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).getCurr()->writeOccupanciesData(sof_a, empty_str)) {
      return Error::handle(name(), L"writeOccupanciesData", Error::ARG, __FILE__, __LINE__);
    }

    // move to the next node
    //
    end_loop = (!const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoNext());
  }

  // restore the state of the list
  //
  const_cast<SingleLinkedList<StatisticalModel>& >(models_d).gotoMark();
   
  if (sof_a.isText()) {
    
    // write the close brace
    //
    if ((long)models_d.length() > 0) {
      sof_a.decreaseIndention();
      sof_a.puts(end_str);
    }
    
    // possibly terminate the statement
    //
    if (pname.length() > 0) {
      sof_a.puts(term);
    }
  }
  
  // exit gracefully
  //
  return true;  
}

// 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: logical error status
//
// this method has the object write itself to an Sof file 
//
boolean MixtureModel::write(Sof& sof_a, long tag_a,
			    const String& name_a) const {

  // write the instance of the object into the Sof file
  //
  long obj_size = 0;
  
  if (sof_a.isText()) {

    // set the size to by dynamic
    //
    obj_size = Sof::ANY_SIZE;
  }
  else {

    // the size index and the size of each element
    //
    obj_size = sofSize();
  }

  // write the object into the sof file's index
  //
  if (!sof_a.put(name_a, tag_a, obj_size)) {
    return false;
  }
  
  // now write the data
  //
  return writeData(sof_a);
}

// method: writeData
//
// arguments:
//  Sof& sof: (input) sof file object
//  const String& pname: (input) parameter name
//
// return: logical error status
//
// this method has the object write itself to an Sof file. it assumes
// that the Sof file is already positioned correctly.
//
boolean MixtureModel::writeData(Sof& sof_a, const String& pname_a) const {
  
  // write a start string if necessary
  //
  sof_a.writeLabelPrefix(pname_a);

  // write the vector of weights
  //
  if ((mode_d == NONE) || (!is_valid_d)) {
    weights_d.writeData(sof_a, PARAM_WEIGHTS);
  }
  else {
    VectorFloat tmp_weights;
    tmp_weights.exp(weights_d);
    tmp_weights.writeData(sof_a, PARAM_WEIGHTS);
  }
    
  // write the models
  //
  models_d.writeData(sof_a, PARAM_MODELS);
  
  // put an end string if necessary
  //
  sof_a.writeLabelSuffix(pname_a);
  
  // exit gracefully
  //
  return true;
}
