// file: ts_tree_3.cc
//

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

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

// method: write_tree_cc
// arguments :
//      Decision_tree** trees : (input) all the decision trees to write
//      int_4 num_trees: (input) number of trees
//      FILE* fp_dt: (output) File pointer to the decision tree file
//
//  return: a logical_1 indicating status
//

// this function is to write all the decision trees into a file
//
logical_1 write_trees_cc(Decision_tree** trees_a, int_4 num_trees_a,
			FILE* fp_dt_a) {
  
  // local variables
  //
  Link_list* curr_list = (Link_list*)NULL;
  Link_list* next_list = (Link_list*)NULL;

  Link_node* curr_lk_node;

  float_4 split_threshold;
  float_4 merge_threshold;
  float_4 num_occ_threshold;

  char_1* cph = (char_1*)NULL;
  int_4 st_pos = 0;
  
  int_4 curr_node_ind;
  int_4 l_child_ind;
  int_4 r_child_ind;
  int_4 node_index = 0;
  logical_1 leaf_flag;
  char_1* attribute = (char_1*)NULL;
  logical_1 direction = (logical_1)NULL;
  Question* opt_question = (Question*)NULL;
  char_1* question = new char_1[TS_QUE_LENGTH];
  
  Dt_node* root;
  Dt_node* curr_dt_node;
  Dt_node* l_child;
  Dt_node* r_child;
  
  int_4 level;
  int_4 state;
  int_4 i;
  int_4 num_nodes = 0;
  logical_1 end_flag;

  // set thresholds
  //
  split_threshold = trees_a[0]->get_split_threshd_cc();
  merge_threshold = trees_a[0]->get_merge_threshd_cc();
  num_occ_threshold = trees_a[0]->get_num_occ_threshd_cc();

  // print the header of the file
  //
  fprintf(fp_dt_a, "# this is the decision tree file including all the trees used for state tying\n");
  fprintf(fp_dt_a, "number_of_trees=%ld\n", num_trees_a);
  fprintf(fp_dt_a, "split_threshold=%f\n", split_threshold);
  fprintf(fp_dt_a, "merge_threshold=%f\n", merge_threshold);
  fprintf(fp_dt_a, "num_occ_threshold=%f\n", num_occ_threshold);
 
  // loop through each tree
  //
  for(i = 0; i<num_trees_a; i++) {

    node_index = 0;
    cph = trees_a[i]->get_cph_cc();
    st_pos = trees_a[i]->get_state_pos_cc();
    
    // count the number of nodes in the tree
    //
    root = trees_a[i]->get_root_cc();
    if (root != (Dt_node*)NULL) {
      num_nodes = 1;     
    }
    
    else {
      num_nodes = 0;
      fprintf(fp_dt_a, "\ntree_index=%ld\n", i);
      fprintf(fp_dt_a, "num_nodes=%ld\n", num_nodes);
      fprintf(fp_dt_a, "cph=%s\n", cph);
      fprintf(fp_dt_a, "st_pos=%ld\n", st_pos);
      continue;
    }
    
    leaf_flag = root->get_leaf_flag_cc();
    
    if(leaf_flag == ISIP_FALSE) {
      
      num_nodes += 2;
      l_child = root->get_l_child_cc();
      r_child = root->get_r_child_cc();
      
      next_list = new Link_list();
      next_list->insert_cc((void_p)l_child);
      next_list->insert_cc((void_p)r_child);
    
      curr_list = next_list;
      next_list = new Link_list();
      end_flag = ISIP_FALSE;
      
      while(end_flag == ISIP_FALSE) {
      
	end_flag = ISIP_TRUE;

	curr_lk_node = curr_list->get_head_cc();
	while(curr_lk_node != (Link_node*)NULL) {
	  
	  curr_dt_node = (Dt_node*)curr_lk_node->get_item_cc();	  
	  leaf_flag = curr_dt_node->get_leaf_flag_cc();
	  
	  if(leaf_flag == ISIP_FALSE) {
	    
	    num_nodes += 2;
	    end_flag = ISIP_FALSE;
	    l_child = curr_dt_node->get_l_child_cc();
	    r_child = curr_dt_node->get_r_child_cc();
	    
	    next_list->insert_cc((void_p)l_child);
	    next_list->insert_cc((void_p)r_child);	  
	  }
	  curr_lk_node = curr_lk_node->get_next_cc();
	}
	
	delete curr_list;
	if(end_flag == ISIP_FALSE) {
	  curr_list = next_list;
	  next_list = new Link_list();
	}
	else {
	  curr_list = (Link_list*)NULL;
	  delete next_list;
	  next_list = (Link_list*)NULL;
	}
      } 
    }  // end of counting nodes
        
    fprintf(fp_dt_a, "\ntree_index=%ld\n", i);
    fprintf(fp_dt_a, "num_nodes=%ld\n", num_nodes);
    fprintf(fp_dt_a, "cph=%s\n", cph);
    fprintf(fp_dt_a, "st_pos=%ld\n", st_pos);
    
    level = 1;
    root = trees_a[i]->get_root_cc();
    root->set_node_index_cc(++node_index);
    curr_node_ind = root->get_node_index_cc() ;
    
    leaf_flag = root->get_leaf_flag_cc();
    curr_list = new Link_list();
    
    curr_list->insert_cc((void_p)root);
    
    // print non leaf node
    //
    if(leaf_flag == ISIP_FALSE) {

      l_child = root->get_l_child_cc();
      r_child = root->get_r_child_cc();

      l_child->set_node_index_cc(++node_index);
      r_child->set_node_index_cc(++node_index);
      
      l_child_ind = l_child->get_node_index_cc();
      r_child_ind = r_child->get_node_index_cc();

      opt_question = root->get_opt_question_cc();
      attribute = opt_question->get_attribute_cc();
      direction = opt_question->get_direction_cc();
      if(direction == ISIP_TRUE) {
	strcpy((char*)question, "L ");
      }
      else {
	strcpy((char*)question, "R ");
      }
      strcat((char*)question, (char*)attribute);
      
      fprintf(fp_dt_a, "N=%ld Level=%ld LF=N Y_CH=%ld N_CH=%ld Q=%s\n",
	      curr_node_ind, level, l_child_ind, r_child_ind, question);
      
      next_list = new Link_list();
      next_list->insert_cc((void_p)l_child);
      next_list->insert_cc((void_p)r_child);
    }

    // print leaf node
    //
    else {
      state = root->get_label_cc();
      fprintf(fp_dt_a, "N=%ld Level=%ld LF=Y State=%ld\n", 
	      curr_node_ind, level, state);
      delete curr_list;
      curr_list = (Link_list*)NULL;
      continue;
    }
    
    delete curr_list;
    curr_list = next_list;
    next_list = new Link_list();
    end_flag = ISIP_FALSE;

    // end_flag will be set to ISIP_TRUE if some node in curr list has
    // children node
    //
    while(end_flag == ISIP_FALSE) {
      
      end_flag = ISIP_TRUE;

      level++;
      curr_lk_node = curr_list->get_head_cc();
      while(curr_lk_node != (Link_node*)NULL) {
	
	curr_dt_node = (Dt_node*)curr_lk_node->get_item_cc();
	curr_node_ind = curr_dt_node->get_node_index_cc();
	leaf_flag = curr_dt_node->get_leaf_flag_cc();

	if(leaf_flag == ISIP_FALSE) {

	  end_flag = ISIP_FALSE;
	  l_child = curr_dt_node->get_l_child_cc();
	  r_child = curr_dt_node->get_r_child_cc();
	  
	  l_child->set_node_index_cc(++node_index);
	  r_child->set_node_index_cc(++node_index);
	  
	  l_child_ind = l_child->get_node_index_cc();
	  r_child_ind = r_child->get_node_index_cc();
	  
	  opt_question = curr_dt_node->get_opt_question_cc();
	  attribute = opt_question->get_attribute_cc();
	  direction = opt_question->get_direction_cc();
	  if(direction == ISIP_TRUE) {
	    strcpy((char*)question, "L ");
	  }
	  else {
	    strcpy((char*)question, "R ");
	  }
	  strcat((char*)question, (char*)attribute);
      
	  fprintf(fp_dt_a, "N=%ld Level=%ld LF=N Y_CH=%ld N_CH=%ld Q=%s\n",
		  curr_node_ind, level, l_child_ind, r_child_ind, question);
	  
	  next_list->insert_cc((void_p)l_child);
	  next_list->insert_cc((void_p)r_child);
	  
	}

	else {
	  state = curr_dt_node->get_label_cc();
	  fprintf(fp_dt_a, "N=%ld Level=%ld LF=Y State=%ld\n",
		  curr_node_ind, level, state);  
	}
	curr_lk_node = curr_lk_node->get_next_cc();
      }
      
      delete curr_list;
      
      if(end_flag == ISIP_FALSE) {
	curr_list = next_list;
	next_list = new Link_list();
      }
      else {
	curr_list = (Link_list*)NULL;
	delete next_list;
	next_list = (Link_list*)NULL;
      }
    }
  
  }  

  delete [] question;
  
  // exit gracefully
  //
  return ISIP_TRUE;
}

















