// file: tr_lat_read_1.cc
//

// system include files
//
#include <memory.h>
#include <string.h>
#include <ctype.h>

// isip include files
//
#include "train_lattice.h"
#include "train_lattice_constants.h"

// method: read_trans_cc
//
// arguments:
//  FILE* fp_in_a: (input) input transcription file
//  int_4* Train_Word_table : (input) the hash table of Train_Word indices
//
// return: a logical_1 indicating status
//
// this method reads in the Train_Lattice from a file
//
logical_1 Train_Lattice::read_trans_cc(FILE* fp_in_a, Train_Hash_table* Train_Words_a) {

  // define some local variables
  //
  char_1 buffer[ISIP_MAX_STRING_LENGTH];
  char_1* buffer_pos = buffer;
  char_1* delimiter = (char_1*)" ";
  int_4 line_length = (int_4)0;
  
  char_1** nodes = new char_1*[TRAIN_LATTICE_MAX_NUM_WORD];
  int_4 num_nodes = (int_4)0;
  int_4 num_arcs = (int_4)0;
  int_4 node_index = (int_4)1;
  int_4 start_node = (int_4)0;
  int_4 end_node = (int_4)0;
  float_8 lm_score = (float_4)0;
  float_8 ac_score = (float_4)0;

  Train_Lattice_node** lnodes = (Train_Lattice_node**)NULL;
  Train_Word* word = (Train_Word*)NULL;
  Train_Hash_cell* hcell = (Train_Hash_cell*)NULL;
  
  // define memory
  //
  memset(buffer, 0, ISIP_MAX_STRING_LENGTH);
  
  // read the Train_Word sequence information from file into a temporary
  // node array
  //
 
  // set the start node
  //
  nodes[node_index] = new char_1[strlen((char*)TRAIN_LATTICE_SENT_START)+1];
  strcpy((char*)nodes[node_index], (char*)TRAIN_LATTICE_SENT_START);
 
  // read data
  //
  fgets((char*)buffer_pos, ISIP_MAX_STRING_LENGTH, fp_in_a);
  
  // find the length of the string read in
  //
  line_length = strlen((char*)buffer_pos);
  buffer_pos[line_length-1] = '\0';
  char* temp_buf = strtok((char*)buffer_pos, (char*)delimiter);
  
  // first Train_Word
  //
  while (temp_buf != (char*)NULL) {
    
    // move the pointer to first non-whitespace
    //
    while (isspace(*temp_buf)) {
      temp_buf++;
    }
    node_index++;
    nodes[node_index] = new char_1[strlen((char*)temp_buf)+1];
    strcpy((char*)nodes[node_index], temp_buf);
    
    //  read the following Train_Word
    //
    temp_buf = strtok((char*)NULL, (char*)delimiter);
  }

  // set the end node
  //
  node_index++;
  nodes[node_index] = new char_1[strlen((char*)TRAIN_LATTICE_SENT_END)+1];
  strcpy((char*)nodes[node_index], (char*)TRAIN_LATTICE_SENT_END);
  
  // count number of nodes and arcs
  //
  num_nodes = node_index + 1;
  num_arcs = num_nodes - 1;
  
  // use above information to generate a Train_Lattice
  //
  set_num_nodes_cc(num_nodes);
  set_num_arcs_cc(num_arcs);
  
  // create the Train_Lattice start node --- this is a dummy node that is
  // not evaluated, it just serves as a starting point for all the
  // sentence start nodes
  //
  lnodes = new Train_Lattice_node*[num_nodes];
  init_nodes_cc(lnodes);
  start_node_d = lnodes[0];
  
  // loop over all nodes
  //
  for (int i = 0; i < num_nodes - 1; i++) {
    
    // set the endpoints for each arc in the Train_Lattice
    //
    start_node = i;
    end_node = i + 1;
    
    // find the corresponding Train_Word in the lexicon
    //
    hcell = Train_Words_a->hash_lookup_cc((char_1*)nodes[end_node]);
    
    // error if Train_Word not found in lexicon
    //
    if (hcell == (Train_Hash_cell*)NULL) {
      printf ("%s\n", (char*)nodes[end_node]);
      error_handler_cc((char_1*)"lat_read_0.cc",
		       (char_1*)"Train_Word does not exist in lexicon");
    }	
    
    // set the item index of the node
    //
    word = (Train_Word*)(hcell->get_item_cc());
    lnodes[end_node]->set_word_cc(word);
    
    // update the prev node and next node pointers for the
    // two nodes corresponding to this arc
    //
    lnodes[start_node]->add_next_node_cc(lnodes[end_node]);
    lnodes[end_node]->add_prev_node_cc(lnodes[start_node]);
    
    // set the acoustic and language Train_Model scores
    //
    lnodes[start_node]->add_lm_score_cc(lm_score);
    lnodes[start_node]->add_ac_score_cc(ac_score);
  }
  
  // free memory
  //
  for (int i = 1; i < num_nodes; i++) {
    delete [] nodes[i];
  }
  delete [] nodes;
  delete [] lnodes;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
