// file: $isip/util/speech/isip_model_converter/imc_lat_0.cc
// version: $Id: imc_lat_0.cc 8977 2003-01-12 06:37:52Z jelinek $
//
// isip include files
//
#include "isip_model_converter.h"

// method: read_lat_cc
//
// arguments:
//  String& lat_filename : (input) file containing prototype lattice
//  File& lat_file : (output) file containing prototype lattice
//  HashTable<String, Ulong>& lex_hash : (input) lexicon hash table
//  Vector<DiGraph<Ulong> >& wrd_graph : (output) word graph
//
// return: a logical flag to indicate success
//
// this method converts the prototype lattice file into Graph<Ulong>
// read by production decoder
//
boolean read_lat_cc(String& lat_filename_a, File& lat_file_a,
		    HashTable<String, Ulong>& lex_hash_a,
		    Vector<DiGraph<Ulong> >& wrd_graph_a) {

  String wrd_string;
  Float lmscale;
  Float wd_penalty;
  Float am_score;
  Float lm_score;
  Ulong num_nodes;
  Ulong num_arcs;
  ulong index = 0;
  ulong count = 0;  
  ulong sent_start_index;
  ulong sent_end_index;
  ulong num_files = 0;
  
  boolean already_connected = true;

  String tmp_in_filename;
  File tmp_in_file;
  
  // declare Ulong objects to hold the node index
  //
  Ulong* node_index = (Ulong*)NULL;
  node_index = new Ulong[2];

  // declare Ulong object to hold the item in the vertex
  //
  Ulong* item = (Ulong*)NULL;
  
  Ulong dummy = 0;
  
  // open the file
  //
  if (!lat_file_a.open(lat_filename_a)) {
    String out(L"error opening");
    out.concat(lat_filename_a);
    Console::put(out);
    Integral::exit();
  }

  // get the index of !SENT_START and !SENT_END
  //
  Ulong* temp_index = lex_hash_a.get(L"!SENT_START");
  sent_start_index = (ulong)(*temp_index);

  temp_index = lex_hash_a.get(L"!SENT_END");  
  sent_end_index = (ulong)(*temp_index);

  // declare a GraphVertex
  //
  GraphVertex<Ulong>** nodes;
  
  // declare string object to hold the items read
  //
  String tmp_str(L"");
  while(!lat_file_a.eof()) {

    // read the input lattice filename
    //
    if (!lat_file_a.get(tmp_in_filename)) {
      break;
    }

    // trim off the excess white space
    //
    tmp_in_filename.trim();

    if (tmp_in_filename.length() <= 0) {
      break;
    }

    // open the lattice file in read mode
    //
    if (!tmp_in_file.open(tmp_in_filename)) {
      String out(L"error opening file ");
      out.concat(tmp_in_filename);
      Console::put(out);
      break;
    }

    // increment the file count
    //
    num_files++;

    // set the length of the Vector<Graph>
    //
    wrd_graph_a.setLength(num_files);

    // set the allocation mode
    //
    wrd_graph_a(num_files - 1).setAllocationMode(DstrBase::USER);

    // traverse through the lattice file
    //
    while(!tmp_in_file.eof()) {
      
      // get the next line
      //
      if(!tmp_in_file.get(tmp_str)) {
	break;
      }
    
      // see if we have reached the arc information
      //
      if(tmp_str(0) == IMC_START_ARC_CHAR) {
	break;
      }
      
      // trim the line and check for empty lines
      //
      tmp_str.trim();
      if (tmp_str.length() <= 0) {
	continue;
      }
      
      String token;
      long pos = 0;
      while (tmp_str.tokenize(token, pos, IMC_DELIMITER_CHAR)) {

	String tag;
	String value;

	long char_pos = -1;

	// grab the tag and value from this substring
	//
	if ((char_pos = token.firstChr(IMC_EQ_DELIMITER_CHAR)) > 0) {
	  token.substr(tag, 0, char_pos);
	  token.substr(value, char_pos+1);
	  tag.debug(L"tag");
	  value.debug(L"tag");
	}
	else {
	  continue;
	}
	
	// read the version
	//
	if(tag.eq(L"VERSION", false)) {
	}
	
	// read the utterance
	//
	else if(tag.eq(L"UTTERANCE", false)) {
	}

	// read the name of the language model
	//
	else if(tag.eq(L"lmname", false)) {
	}
	
	// read the lmscale value
	//
	else if(tag.eq(L"lmscale", false)) {
	  lmscale.assign(value);
	  lmscale.debug(L"LMSCALE");
	  value.debug(L"value");
	}
	
	// read the word insertion penalty value
	//
	else if(tag.eq(L"wdpenalty", false)) {
	  wd_penalty.assign(value);
	  wd_penalty.debug(L"wdpenalty");
	}
	
	// read the vocab
	//
	else if(tag.eq(L"vocab", false)) {
	}
	
	// read the hmms
	//
	else if(tag.eq(L"hmms", false)) {
	}
	
	// read the number of nodes
	//
	else if(tag.eq(L"N", false)) {
	  num_nodes.assign(value);
	  num_nodes.debug(L"Number of Nodes");
	}
	
	// read the number of arcs
	//
	else if(tag.eq(L"L", false)) {
	  num_arcs.assign(value);
	  num_arcs.debug(L"Number of Arcs");
	}
      }
    }

    index = (ulong)num_nodes;
    printf("Number of nodes = %lu\n", index);
    
    // create the vertices
    //
    nodes = new GraphVertex<Ulong>*[index];
    ulong start_index = 0;
    ulong end_index = 0;
    
    // set the start and terminal vertex
    //
    nodes[0] = wrd_graph_a(num_files - 1).getStart();
    
    for (long i = 1; i < (long)index ; i++) {
      nodes[i] = (GraphVertex<Ulong>*)NULL;
    }
    
    // traverse the rest of the file and construct the graph
    //
    while(!tmp_in_file.eof()) { 
      
      printf("Inside second while Statement\n");
      
      // trim the line and check for empty lines
      //
      tmp_str.trim();
      if (tmp_str.length() <= 0) {
	continue;
      }
      
      String token;
      long pos = 0;
      while (tmp_str.tokenize(token, pos, IMC_DELIMITER_CHAR)) {

	String tag;
	String value;

	long char_pos = -1;

	// grab the tag and value from this substring
	//
	if ((char_pos = token.firstChr(IMC_EQ_DELIMITER_CHAR)) > 0) {
	  token.substr(tag, 0, char_pos);
	  token.substr(value, char_pos+1);
	  tag.debug(L"tag");
	  value.debug(L"tag");
	}
	else {
	  continue;
	}
	
	// get the arc index
	//
	if(tag.eq(L"J", false)) {
	  count++;
	}
	
	// get the start node of the arc
	//
	else if(tag.eq(L"S", false)) {
	  node_index[0].assign(value);
	  start_index = (ulong)node_index[0];
	  if(nodes[start_index] == (GraphVertex<Ulong>*)NULL) {
	    nodes[start_index] =
	      wrd_graph_a(num_files - 1).insertVertex(&dummy);
	    nodes[start_index]->setItem((Ulong*)NULL);
	  }
	  printf("Start index = %lu\n", start_index);
	}
	
	// end node of the arc
	//
	else if(tag.eq(L"E", false)) {
	  node_index[1].assign(value);
	  end_index = (ulong)node_index[1];
	  if(nodes[end_index] == (GraphVertex<Ulong>*)NULL) {
	    nodes[end_index] =
	      wrd_graph_a(num_files - 1).insertVertex(&dummy);
	    nodes[end_index]->setItem((Ulong*)NULL);	  
	  }
	  printf("End index = %lu\n", end_index);	
	}
	
	// word represented by the arc
	//
	else if(tag.eq(L"W", false)) {
	  
	  // get the index for the word from the hash table
	  //
	  value.trim();
	  value.debug(L" WORD IS = ");
	  item = lex_hash_a.get(value);
	  item->debug(L"WORD INDEX =");
	  
	  // set the item of the node
	  //
	  if(nodes[end_index]->getItem() == (Ulong*)NULL) {
	    nodes[end_index]->setItem(item);
	  }
	}
	
	// read the pronunciation variant
	//
	else if(tag.eq(L"v", false)) {
	  am_score.assign(value);
	}
	// read the acoustic score
	//
	else if(tag.eq(L"a", false)) {
	  am_score.assign(value);
	}
	
	// read the lm score
	//
	else if(tag.eq(L"l", false)) {
	  lm_score.assign(value);
	}
      }
      
      Ulong* str;
      
      // add the arc between the two nodes
      //
      wrd_graph_a(num_files - 1).insertArc(nodes[start_index],
					   nodes[end_index],
					   true, 
					   (float)((double)lm_score *
						   log((double)10)));
      
      str = nodes[end_index]->getItem();
      str->debug(L"End Node Item");
      
      
      // we also need to connect the !SENT_END with the graph terminal
      // vertex
      //
      if((nodes[end_index]->getItem()->eq(sent_end_index)) &&
	 (already_connected)) {
	wrd_graph_a(num_files - 1).insertArc(nodes[end_index],
			     wrd_graph_a(num_files - 1).getTerm(),
					     true,
					     (float)log((double)1.0));
	already_connected =  false;
      }
      
      // get the next line
      //    
      if(!tmp_in_file.get(tmp_str)) {
	break;
      }    
    }

    // close the input lattice file
    //
    tmp_in_file.close();
  }
  
  return lat_file_a.close();
}

