// file: lat_to_nbest.cc
//
// this utility does the lattice to nbest lst conversion
//

// isip include files
//
#include "lat_to_nbest.h"
#include "lat_to_nbest_constants.h"

// main program
//
int main(int_4 argc, char_1** argv) {

  // variables to hold commandline parameters
  //
  char_1* params_file = (char_1*)NULL;

  // read and decipher the commandline
  //
  read_cmdline_cc(argc, argv, params_file);

  // variables to hold data in parameters file
  //
  char_1* lexicon_file = (char_1*)NULL;
  char_1* input_file = (char_1*)NULL;
  char_1* output_file = (char_1*)NULL;
  
  int_4 num_nbest = LTON_NUM_NBEST;

  // language model
  //
  float_8 lm_scale = LTON_LM_SCALE;
  float_8 wd_penalty = LTON_WORD_PENALTY;
  int_4 ngram_size = LTON_NGRAM_ORDER;
  char_1* lm_file = (char_1*)NULL;

  // pruning threshold
  //
  float_8 beam_width = (float_8)DEC_NUM_NBEST_BEAM;
  int_4 max_paths = DEC_NUM_NBEST_MAX_PATH;
  
  // open parameter file
  //
  FILE* fp = (FILE*)NULL;
  open_file_cc(fp, params_file, (char_1*)"r");

  // read parameters
  //
  read_params_cc(fp, lexicon_file, lm_file, input_file, output_file,
		 ngram_size, num_nbest, max_paths, beam_width, lm_scale,
		 wd_penalty);

  // clean up
  //
  fclose(fp);  
  delete [] params_file;
  params_file = (char_1*)NULL;

  // create a memory manager
  //
  Memory_manager* manager = new Memory_manager(LTON_DEFAULT_BLOCK_SIZE,
					       LTON_NODE_BLOCK_SIZE);

  // create a decoder
  //
  Decoder* isip_decoder = new Decoder();

  // initialize the decoder
  //
  isip_decoder->set_lmscale_cc(lm_scale);
  isip_decoder->set_wdpenalty_cc(wd_penalty);
  isip_decoder->set_function_mode_cc(LTON_FUNCTION);
  isip_decoder->set_ngram_order_cc(ngram_size);
  isip_decoder->set_num_nbest_cc(num_nbest);
  isip_decoder->set_manager_cc(manager);

  // read the lexicon
  //
  if (lexicon_file == (char_1*)NULL) {
    fprintf(stdout, "Error: lexicon file not specified\n");
    exit(ISIP_PROTO_ERROR);
  }
  fp = (FILE*)NULL;
  open_file_cc(fp, lexicon_file, (char_1*)"r");
  
  fprintf(stdout, "Reading lexicon...\n");
  isip_decoder->read_lexicon_cc(fp);
  fclose(fp);
  delete [] lexicon_file;
  lexicon_file = (char_1*)NULL;

  /*
  // check if the ngram lm file exists
  //
  if (lm_file == (char_1*)NULL) {
    fprintf(stdout, "Error: language model file not specified\n");
    exit(ISIP_PROTO_ERROR);
  }
  open_file_cc(fp, lm_file, (char_1*)"r");
  
  // load the ngram
  //
  fprintf(stdout, "Reading language model data...\n");
  // isip_decoder->read_ngram_cc(fp);
  fclose(fp);
  */
  
  // open input and output lists
  //
  FILE* fpin_list = (FILE*)NULL;
  FILE* fpout_list = (FILE*)NULL;
    
  // open the file containing the list of input lattice files
  //
  if (input_file == (char_1*)NULL) {
    fprintf(stdout, "Error: input lattice file list not specified\n");
    exit(ISIP_PROTO_ERROR);
  }
  open_file_cc(fpin_list, input_file, (char_1*)"r");

  // open the file containing the list of output files
  //
  if (output_file == (char_1*)NULL) {
    fprintf(stdout, "Error: output file list not specified\n");
    exit(ISIP_PROTO_ERROR);
  }
  open_file_cc(fpout_list, output_file, (char_1*)"r");

  // define file pointers for data files
  //
  FILE* fpi = (FILE*)NULL;
  FILE* fpo = (FILE*)NULL;
    
  // allocate memory for individual, lattice and output files
  //
  char_1* lattice_in = new char_1[ISIP_MAX_STRING_LENGTH];
  char_1* hyp_file = new char_1[ISIP_MAX_STRING_LENGTH];

  // read the corresoponding data file from each list and process one
  // by one
  //
  while (fgets((char*)lattice_in, ISIP_MAX_STRING_LENGTH, fpin_list) !=
	 (char*)NULL) {
      
    // expand the input filename
    //
    Decoder::expand_filename_cc(lattice_in);
    open_file_cc(fpi, lattice_in, (char_1*)"r");
      
    // print status message
    //
    fprintf(stdout, "Processing data: %s...\n", lattice_in);
    fflush(stdout);
      
    // make sure there is a corresponding output file for each input
    // file
    //
    if (fgets((char*)hyp_file, ISIP_MAX_STRING_LENGTH, fpout_list) ==
	(char*)NULL) {
      fprintf(stdout, "Error : mismatch in the number of ");
      fprintf(stdout, "input mfcc files and output files.\n");
      exit(ISIP_PROTO_ERROR);
    }
    Decoder::expand_filename_cc(hyp_file);
    open_file_cc(fpo, hyp_file, (char_1*)"w");
      
    // perform the nbest here
    //
    isip_decoder->lattice_to_nbest_cc(fpi, fpo, max_paths, beam_width);
				      
    // close the files
    //
    fclose(fpi);
    fclose(fpo);
  } // end while loop over all files
    
  // close all files
  //
  fclose(fpin_list);
  fclose(fpout_list);
    
  // free memory
  //
  if (lattice_in != (char_1*)NULL) {
    delete [] lattice_in;
    lattice_in = (char_1*)NULL;
  }

  if (hyp_file != (char_1*)NULL) {
    delete [] hyp_file;
    hyp_file = (char_1*)NULL;
  }

  // free decoder
  //
  delete isip_decoder;
  
  // free memory
  //
  if (lm_file != (char_1*)NULL) {
    delete [] lm_file;
    lm_file = (char_1*)NULL;
  }

  if (input_file != (char_1*)NULL) {
    delete [] input_file;
    input_file = (char_1*)NULL;
  }
  
  if (output_file != (char_1*)NULL) {
    delete [] output_file;
    output_file = (char_1*)NULL;
  }
  
  // exit gracefully
  //
  exit(ISIP_NO_ERROR);
}
