// file: lxt_tree_1.cc
//
// function to count number of lex nodes in a tree
//

// isip include files
//
#include "lex_tree.h"
#include "lex_tree_constants.h"

// method: build_tree_cc
//
// arguments:
//  Ngram* ngram : (input) the ngram language model
//  Hash_table* lexicon : (input) the lexicon
//
// return: a logical_1 to indicate success
//
// this method loops over all the unigram words in the ngram LM, and
// for each pronunciations of the word, it checks phone-by-phone if
// the current phone is already on the correct branch of the tree and
// inserts the word in the corresponding node
//
logical_1 Lex_tree::build_tree_cc(Ngram* ngram_a, Hash_table* lexicon_a) {
  
  // phone / word parameters
  //
  int_4 phone = (int_4)-1;
  int_4 num_prons = (int_4)0;
  int_4* num_ph = (int_4*)NULL;
  int_4** phlist = (int_4**)NULL;

  // dummy lexical nodes
  //
  Lex_node* curr_node = (Lex_node*)NULL;
  Lex_node* next_node = (Lex_node*)NULL;
  Lex_node* stop_node = (Lex_node*)NULL;

  // memory manager
  //
  Memory_manager* manager = Link_list::get_manager_cc();

  // set the head node
  //
  if (head_d == (Lex_node*)NULL) {
    head_d = manager->new_lex_cc();
    head_d->set_phone_cc(LXN_START_PHONE);
    head_d->set_type_cc(LXN_NGRAM);
  }

  // mark status as true i.e. active
  //
  status_d = ISIP_TRUE;

  // get the unigrams list
  //
  Ngram_list* unigrams = ngram_a->get_list_cc(0);

  // get each word in the unigram table
  //
  Word* word = (Word*)NULL;
  int_4 num_uni = unigrams->get_num_cc();
  Ngram_node** uninodes = unigrams->get_nodes_cc();

  // loop over all nodes
  //
  for (int_4 k = 0; k < num_uni; k++) {

    // get the word
    //
    word = uninodes[k]->get_word_cc();
    
    // the sentence start word has already been accounted for
    //
    if (word->get_index_cc() != LXT_SENT_START_WORD) {
      
      // create a stop node
      //
      stop_node = manager->new_lex_cc();
      stop_node->set_phone_cc(LXN_STOP_PHONE);
      stop_node->set_type_cc(LXN_NGRAM);
      stop_node->add_word_cc(uninodes[k]);
      
      // get the pronunciations for this word
      //
      num_prons = word->get_num_prons_cc();
      phlist = word->get_phone_list_cc();
      num_ph = word->get_num_phones_cc();
      
      // if this word has no pronunciations, check if it reperesents
      // another language model
      //
      if (*(word->get_name_cc()) == ISIP_DOLLAR || (num_prons == 0)) {

	// add the stop node for this word directly to the head node
	//
	head_d->add_child_cc(stop_node);
	head_d->set_word_end_cc(ISIP_TRUE);
      }

      // otherwise grow the tree
      //
      else {

	// loop over all the pronunciations for this word
	//
	for (int_4 i = 0; i < num_prons; i++) {
	  
	  // set the next node as current
	  //
	  next_node = head_d;
	  
	  // loop over all phones in this pronunciations
	  //
	  for (int_4 j = 0; j < num_ph[i]; j++) {
	    
	    // set the current node
	    //
	    curr_node = next_node;
	    
	    // the jth phone of this ith pronunciation
	    //
	    phone = phlist[i][j];
	    
	    // get the node in the tree that contains this phone
	    //
	    next_node = curr_node->make_node_cc(phone);
	    next_node->add_word_cc(uninodes[k]);
	    next_node->set_type_cc(LXN_NGRAM);
	    
	  } // end for j
	  
	  // add the stop node at the end of word and set word end
	  // flag
	  //
	  next_node->add_child_cc(stop_node);
	  next_node->set_word_end_cc(ISIP_TRUE);
	  
	} // end loop over all pronunciations
      } // end else grow the tree
    } // end if this is not sentence start word
  } // end for loop over k
  
  // exit gracefully
  //
  return ISIP_TRUE;  
}
