// file: $USFS/util/error_eval/v6.1/error_proc_0.cc
//

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

// isip include files
//
#include "error_eval.h"
#include "error_eval_constants.h"

#ifndef __ISIP_IMAGE_ANALYSIS
#include <image_analysis.h>
#endif

#ifndef __ISIP_PPM
#include <ppm.h>
#endif

// function: eval_seg_cc
//
// arguments:
//  char_1* result_file: (input) the result file being evaluated
//  char_1* ref_filelist: (input) the reference segmentation data file list
//
// return:
//  a logical_1 value indicating the status
//
// this function evaluates the performance of the automatic segmentation
//
logical_1 eval_seg_cc(char_1* result_file_a, char_1* ref_filelist_a) {

  // declare local variables
  //
  Ppm ppm;
  Image_analysis ia;
  FILE* fp_result = (FILE*)NULL;
  float_8 error_rate = 0;
  int_4 error_cnt = 0, total_cnt = 0;
  float_8 error_rate_local = 0;
  int_4 error_cnt_local = 0, total_cnt_local = 0;
  int_4 confusion[EE_NUM_TRANS][EE_NUM_TRANS] = {
    {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0, 0},
  };
  
  // define the transcriptions
  //
  char_1* trans_ref[EE_NUM_TRANS] = {
    (char_1*)"tree", (char_1*)"foliage", (char_1*)"bush",
    (char_1*)"grass", (char_1*)"bgsky", (char_1*)"sky"
  };
  
  char_1* temp_buf = (char_1*)NULL;
  char_1* image_file = (char_1*)NULL;
  char_1* seg_file = (char_1*)NULL;
  char_1* dummy = new char_1[2];
  
  // set the memory manager for the Link_list class
  //
  Memory_manager* manager = new Memory_manager(1000, 1000);
  Link_list::set_manager_cc(manager);
		  
  // open the result file
  //
  if ((fp_result = fopen((char*)result_file_a, "r")) == (FILE*)NULL) {
    fprintf(stdout, "%s: error opening file\n", result_file_a);
    return ISIP_FALSE;
  }
  
  char_1* str_buf = new char_1[ISIP_MAX_STRING_LENGTH];
  memset(str_buf, 0, ISIP_MAX_STRING_LENGTH);
  
  // loop over the result file and do statistics
  //
  while(fgets((char*)str_buf, ISIP_MAX_STRING_LENGTH, fp_result)
	!= (char*)NULL) {

    // cut off the newline character
    //
    str_buf[strlen((char*)str_buf) - 1] = ISIP_NULL;
    
    // check for the image file name
    //
    if (str_buf[0] == ISIP_POUND) {

      // the current string is an image file name
      //
      int_4 string_len = strlen((char*)str_buf);
      temp_buf = new char_1[string_len];
      image_file = new char_1[ISIP_MAX_STRING_LENGTH];
      memset((char*)temp_buf, 0, string_len);
      memset((char*)image_file, 0, ISIP_MAX_STRING_LENGTH);

      // read the image file name, note we need to discard the first "#"
      //
      sscanf((char*)str_buf, "%1s %s", dummy, temp_buf);

      // expand the file name if necessary
      //
      ppm.expand_cc(image_file, temp_buf);

      seg_file = new char_1[ISIP_MAX_STRING_LENGTH];
      memset((char*)seg_file, 0, ISIP_MAX_STRING_LENGTH);
      
      // find the corresponding segmentation file from the list
      //
      if (get_next_segfname_cc(seg_file, image_file, ref_filelist_a)
	  == ISIP_FALSE) {
	fprintf(stdout, "%s: error reading file\n", ref_filelist_a);
	return ISIP_FALSE;
      }

      // load reference segmentation data
      //
      if (ia.load_polygons_cc(seg_file) == ISIP_FALSE) {
        fprintf(stdout, "%s: error loading data\n", seg_file);
        return ISIP_FALSE;
      }

      // output image file name and statistics for the previous image
      //
      if (total_cnt_local != 0) {
	error_rate_local = (float_8)error_cnt_local / (float_8)total_cnt_local;
	fprintf(stdout, "local error rate: %f\n", error_rate_local);
	fprintf(stdout, "total blocks: %ld\n", total_cnt_local);
	fprintf(stdout, "wrong blocks: %ld\n", error_cnt_local);
	error_rate_local = 0.0;
	total_cnt_local = 0;
	error_cnt_local = 0;
      }
      fprintf(stdout, "\n%s\n", image_file);
    }

    // else check for blank lines before loading classification results
    //
    else if(sscanf((char*)str_buf, "%1s", dummy) > 0) {

      // declare variables for error computation
      //
      float_8 dummy_score = 0.0;
      int_4 result = 0;
      int_4 off_w = 0;
      int_4 off_h = 0;
      int_4 blk_w = 0;
      int_4 blk_h = 0;

      // read in data for one block
      //
      sscanf((char*)str_buf, "%lf %lf %lf %lf %lf %lf %ld %ld %ld %ld %ld",
	     &dummy_score, &dummy_score, &dummy_score, &dummy_score,
	     &dummy_score, &dummy_score, &result, &off_w, &off_h,
	     &blk_w, &blk_h);
      
      int_4 center_x = off_w + blk_w / 2;
      int_4 center_y = off_h + blk_h / 2;
      char_1* trans = (char_1*)NULL;
      int_4 ref = -1;
      
      // check if the center of the block is inside one of the listed polygons
      //
      if (ia.is_inside_cc(center_x, center_y, trans) == ISIP_TRUE) {

	// check if the classification result is correct
	//
	if (strcmp((char*)trans, (char*)trans_ref[result]) != 0) {

	  // error statistics
	  //
	  for (int_4 i=0; i<EE_NUM_TRANS; i++) {
	    if (strcmp((char*)trans, (char*)trans_ref[i]) == 0) {
	      ref = i;
	      break;
	    }
	  }
	  
	  if (ref == (-1)) {
	    fprintf(stdout, "eval_seg_cc: error transcription\n");
	    return ISIP_FALSE;
	  }
	  else {
	    confusion[result][ref]++;
            error_cnt++;
	    total_cnt++;
	    error_cnt_local++;
	    total_cnt_local++;	    
	  }
	}
	else {
	  confusion[result][result]++;
	  total_cnt++;
	  total_cnt_local++;	  
	}
      }

      // release memory
      //
      if (trans != (char_1*)NULL) {
	delete [] trans;
	trans = (char_1*)NULL;
      }
    }
  }

  // output local statistics
  //
  error_rate_local = (float_8)error_cnt_local / (float_8)total_cnt_local;
  fprintf(stdout, "local error rate: %f\n", error_rate_local);
  fprintf(stdout, "total blocks: %ld\n", total_cnt_local);
  fprintf(stdout, "wrong blocks: %ld\n\n", error_cnt_local);

  // compute error rate
  //
  error_rate = (float_8)error_cnt / (float_8)total_cnt;
  
  // print statistical information
  //
  fprintf(stdout, "the result file: %s\n", result_file_a);
  fprintf(stdout, "the error rate: %f\n", error_rate);
  fprintf(stdout, "number of blocks processed: %ld\n", total_cnt);
  fprintf(stdout, "number of blocks classified incorrectly: %ld\n", error_cnt);
  fprintf(stdout, "confusion matrix:\n");
  for (int_4 i=0; i<EE_NUM_TRANS; i++) {
    for (int_4 j=0; j<EE_NUM_TRANS; j++) {
      fprintf(stdout, "%7ld", confusion[i][j]);
    }
    fprintf(stdout, "\n");
  }
  
  // close files
  //
  fclose(fp_result);

  // release memory
  //
  if(str_buf != (char_1*)NULL) {
    delete [] str_buf;
  }
  if(temp_buf != (char_1*)NULL) {
    delete [] temp_buf;
  }
  if(image_file != (char_1*)NULL) {
    delete [] image_file;
  }
  if(seg_file != (char_1*)NULL) {
    delete [] seg_file;
  }
  if(dummy != (char_1*)NULL) {
    delete [] dummy;
  }
  
  // exit gracefully
  //
  return ISIP_TRUE;
}
