// file: ts_model_0.cc
//

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

// isip include files
//
#include "tie_state.h"
#include "tie_state_constants.h"

// method: write_models_cc
//
// arguments:
//   FILE* fp_out_model : (input)  file pointer to model file
//   int_4 num_mono : (input)  number of monophones
//   char_1** mono : (input)  monophone list
//   int_4 num_models  : (input) number of models
//   Decision_tree** trees  : (input) pointers to decision trees
//   int_4** l_context: (input) the left context of states
//   int_4** r_context: (input) the right context of states
//   int_4* trans_map : (input)  map between central phone index and
//                                      transition matrix index
//   int_4* num_states : (input) number of state in each model
//
// return: a logical_1 showing status
//
// this method writes the models to file 
//
logical_1 write_models_cc(FILE* fp_out_model_a, int_4 num_mono_a,
			  char_1** mono_a, int_4 num_models_a,
			  int_4* trans_map_a, Decision_tree** trees_a,
			  int_4** l_context_a, int_4** r_context_a,
			  int_4* ph_map_a, int_4* num_states_a) {
  
  // define variables
  //
  int_4 num_trees = (num_mono_a-5)*3;
  int_4 num_states;
  int_4* state_index;
  int_4 ph_index;
  int_4 st_pos;
  Link_list* leaf_list;
  Link_node* leaf_node;
  Dt_node* dt_node;
  int_4 model_index;
  int_4 trans_index;
  int_4 label = 0;

  char_1* lph = (char_1*)NULL;
  char_1* cph = (char_1*)NULL;
  char_1* rph = (char_1*)NULL;

  int_4 n_cph = (int_4)0;
  int_4* phn = new int_4[3];

  int_4 i;
  int_4 j;
  
  char_1** phones = new char_1*[num_models_a];
  int_4* transitions = new int_4[num_models_a];
  int_4** states = new int_4*[num_models_a];
  
  for(i = 0; i < num_models_a; i++) {
    phones[i] = new char_1[ISIP_MAX_STRING_LENGTH];
    states[i] = new int_4[3];
  }
    
  for(i = 0; i < num_trees; i++) {
    leaf_list = trees_a[i]->get_leaf_list_cc();
    leaf_node = leaf_list->get_head_cc();
    cph = trees_a[i]->get_cph_cc();
    st_pos = trees_a[i]->get_state_pos_cc();

    // get the transition index from the central phone
    //
    for(j = 0; j < num_mono_a; j++) {		
      if(strcmp((char*)cph, (char*)mono_a[j])==0) {
	n_cph = j;
	break;
      }
    }

    trans_index = trans_map_a[n_cph];
    
    // loop through all the leaf nodes
    //
    while(leaf_node!=(Link_node*)NULL) {
      dt_node = (Dt_node*)(leaf_node->get_item_cc());
      num_states = dt_node->get_num_states_cc();
      state_index = dt_node->get_state_index_cc();
      label = dt_node->get_label_cc();
      
      for(j = 0; j < num_mono_a;  j++) {	    
	if(strcmp((char*)cph, (char*)mono_a[j])==0) {
	  n_cph = j;
	  phn[1] = n_cph;
	  break;
	}
      }
      
      for(j = 0; j < num_states; j++) {
		
	if(l_context_a[state_index[j]][0] != -5) {
	  
	  phn[0] = l_context_a[state_index[j]][0] ;
	  lph = mono_a[l_context_a[state_index[j]][0]];
	  if(r_context_a[state_index[j]][0] != -5) {
	    phn[2] = r_context_a[state_index[j]][0];
	    rph = mono_a[r_context_a[state_index[j]][0]];
	  }
	  else {
	    phn[2] = 0;
	  }
	}

	else {
	  phn[0] = 0;
	  if(r_context_a[state_index[j]][0] != -5) {
	    rph = mono_a[r_context_a[state_index[j]][0]];
	    phn[2] = r_context_a[state_index[j]][0];
	  }
	  else {
	    phn[2] = 0;
	  }
	}

	// get the phone index
	//
	ph_index = 0;
	for (int_4 i = 0; i < 3; i++) {
	  ph_index += phn[i] * (int_4)pow(num_mono_a, i);    
	}
	model_index = ph_map_a[ph_index];
	
	states[model_index][st_pos-1] = label;
	transitions[model_index] = trans_index;
	
	if(phn[0] != 0) {
	  strcpy((char*)phones[model_index], (char*)lph);
	  strcat((char*)phones[model_index], "-");
	  strcat((char*)phones[model_index], (char*)cph);
	  if(phn[2] !=0) {
	    strcat((char*)phones[model_index], "+");
	    strcat((char*)phones[model_index], (char*)rph);
	  }
	}
	else {
	  strcpy((char*)phones[model_index], (char*)cph);
	  if(phn[2] !=0) {
	    strcat((char*)phones[model_index], "+");
	    strcat((char*)phones[model_index], (char*)rph);
	  }
	}
      }
      leaf_node = leaf_node->get_next_cc();      
    }    
  }


  // output the models other than the special ones with the new states
  //
  for(i = 3; i < num_models_a; i++) {
    if(strcmp((char*)phones[i],"") != 0) {      
      fprintf(fp_out_model_a, "index:  %ld\n", i);
      fprintf(fp_out_model_a, "phone:  %s\n", phones[i]);
      fprintf(fp_out_model_a, "num_states:  %ld\n", num_states_a[i]);
      fprintf(fp_out_model_a, "transitions:  %ld\n", transitions[i]);
      fprintf(fp_out_model_a, "states:  0 %ld %ld %ld 0\n", states[i][0],
	      states[i][1], states[i][2]);
      fprintf(fp_out_model_a, "\n");
    }
  }
  
  // free memory
  //
  delete [] phn;
  delete [] transitions;
  
  for(i = 0; i < num_models_a; i++) {
    delete [] phones[i] ;
    delete [] states[i] ;
  }  
  delete [] states;
  delete [] phones;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
