/* -*- c-file-style: "GNU" -*- */
/*
 * Copyright © CNRS, INRIA, Université Bordeaux 1
 * See COPYING in top-level directory.
 */

#define _GNU_SOURCE
#include <stdio.h>

#include "ev_codes.h"
#include "eztrace_convert_core.h"
#include "eztrace_list.h"
#include "eztrace_convert.h"
#include "eztrace_hook.h"
#include "eztrace_stats_core.h"

/* name of the output file */
static char *output_filename = "paje";
static char* output_path = NULL;

/* Find the next trace event to handle
 * return the trace id that correspond to the trace to be handled
 */
static int __get_cur_ev() {
  int i;
  float min_time = FLT_MAX;
  int min_trace = 0;

  /* First, make all the non-started traces progress */
  if(NB_START < NB_TRACES)
    for(i=0;i<NB_TRACES;i++)
      if(! get_traces(i)->start) {
        *get_skip() = 0;
	return i;
      }

  for(i=0; i<NB_TRACES; i++) {
    /* Only considere traces that
     * - have events to be handled
     * - do not wait for an external event
     */
    if(!get_traces(i)->done && !get_traces(i)->skip && CUR_TIME(i) < min_time) {
      min_time = CUR_TIME(i);
      min_trace = i;
    }
    /* reset the skip value so that the trace is not skipped forever */
    if(!SKIP)
      get_traces(i)->skip = 0;
  }
  SKIP = 0;

  return min_trace;
}


static void
usage (int argc  __attribute__((unused)), char **argv)
{
  fprintf (stderr,
	   "Usage : %s [-v] [-o output_dir] input_filename input_filename ... \n",
	   argv[0]);
}

static void
parse_args (int argc, char **argv)
{
  int i;
  for (i = 1; i < argc; i++)
    {
      if (strcmp (argv[i], "-o") == 0) {
	output_path = argv[++i];
	if (i >= argc) {
	  fprintf(stderr,"-o needs a parameter\n");
	  exit(-1);
	}
      }
      else if (strcmp (argv[i], "-v") == 0)
	VERBOSE = 1;
      else if(strcmp (argv[i], "-h") == 0) {
	usage (argc, argv);
	exit (-1);
      } else {

	eztrace_convert_init(argc-i);
	get_traces(NB_TRACES)->input_filename = argv[i];
	NB_TRACES++;
      }
    }

  if(NB_TRACES < 1)
    {
      usage (argc, argv);
      exit (-1);
    }
}

/*
 * This program should be used to parse the log file generated by FxT
 */
int
main (int argc, char **argv)
{
  int ret;
  int fd_in;

  set_cur_mode(EZTRACE_STATS);

  load_modules(1);

  /* parse the arguments passed to this program */
  parse_args (argc, argv);

  if(!output_path)
    asprintf(&output_path, "/tmp/eztrace_stats_%s", getenv("USER"));
  eztrace_stats_set_output_dir(output_path);

  __init_modules();

  int i;
  /* initialize the traces array */
  for(i=0;i< NB_TRACES; i++) {
    /* open the trace file */
    fxt_t fut = fxt_open (get_traces(i)->input_filename);
    if (!fut)
      {
	perror ("fxt_open:");
	exit (-1);
      }

    get_traces(i)->delay = 0;
    get_traces(i)->rank = i;
    get_traces(i)->id = i;
    get_traces(i)->done = 0;
    get_traces(i)->skip = 0;

    eztrace_create_containers(i);

    /* if several traces are loaded, this means that MPI was used,
     * so let's skip all the first events until MPI_Init is detected
     */
    if(NB_TRACES > 1)
      get_traces(i)->start = 0;
    else {
      CREATE_TRACE_ID_STR(get_traces(i)->trace_id, 0);
      get_traces(i)->start = 1;
      NB_START= 1;
      eztrace_create_ids(get_traces(i)->rank);
    }

    get_traces(i)->block = fxt_blockev_enter (fut);

    ret = fxt_next_ev (get_traces(i)->block, FXT_EV_TYPE_64, (struct fxt_ev *) &get_traces(i)->ev);
    if (ret != FXT_EV_OK)
      {
	fprintf (stderr, "no more block ...\n");
	break;
      }
    get_traces(i)->start_time = get_traces(i)->ev.time;
  }

  /* todo: 0 or i ? */
  set_cur_trace(get_traces(0));
  set_cur_ev(&get_traces(i)->ev);

  struct eztrace_event_handler* handler_info =  get_handler_info();

  /* OK, let's work ! */
  while (handler_info->nb_done < NB_TRACES)
    {
      set_cur_mode(EZTRACE_STATS);
      handle_one_event(NULL);
    }

  /* finally, call the print_stats callback for all plugins */
  __print_stats();

  return 0;
}
