/* LICENSE:
  =========================================================================
    CMPack'04 Source Code Release for OPEN-R SDK 1.1.5-r2 for ERS7
    Copyright (C) 2004 Multirobot Lab [Project Head: Manuela Veloso]
    School of Computer Science, Carnegie Mellon University
    All rights reserved.
  ========================================================================= */

#ifndef INCLUDED_Reporting_h
#define INCLUDED_Reporting_h

#include <stdio.h>

#include "DogTypes.h"
#include "CircBufPacket.h"
#include "SystemUtility.h"

class EventRateReporter {
private:
  const char *eventName;
  ulong timeReportRate;
  ulong countReportRate;
  ulong lastReport;
  ulong count;
  PacketStream **buffer;
 public:
  EventRateReporter(const char *name,ulong time_report_rate, ulong count_report_rate, PacketStream **buffer_param) :
    eventName(name),
    timeReportRate(time_report_rate),
    countReportRate(count_report_rate),
    lastReport(0UL),
    count(0UL),
    buffer(buffer_param) {
  }
  
  void addToCount(bool dodump) {
    count++;
    ulong time;

    time=GetTime();

    if(count >= countReportRate || time-lastReport > timeReportRate) {
      if((*buffer)!=NULL) {
	if (dodump) {
	  pprintf((*buffer),"%s:rate %f\n",eventName,
		  (double)count / ((time-lastReport)/1000000.0));
	}
      }
      lastReport=time;
      count=0UL;
    }
  }
};

class EventTimeReporter {
private:
  const char *eventName;
  ulong totalTimeReportRate;
  ulong timeReportRate;
  ulong countReportRate;
  ulong lastReport;
  ulong count;
  ulong totalTime;
  PacketStream **buffer;
public:
  class EventTimer {
    bool do_dump;
  public:
    EventTimeReporter *etr;
    ulong start_time;

    EventTimer(EventTimeReporter *_etr,bool _do_dump) {
      etr = _etr;
      start_time = GetTime();
      do_dump = _do_dump;
    }

    ~EventTimer() {
      ulong end_time = GetTime();
      ulong elapsed_time = end_time - start_time;
      etr->addTimeEvent(elapsed_time,do_dump);
    }
  };

  EventTimeReporter(const char *name,
                    ulong total_time_report_rate, ulong time_report_rate, ulong count_report_rate,
                    PacketStream **buffer_param) :
    eventName(name),
    totalTimeReportRate(total_time_report_rate),
    timeReportRate(time_report_rate),
    countReportRate(count_report_rate),
    lastReport(0UL),
    count(0UL),
    totalTime(0UL),
    buffer(buffer_param) {
  }

  void addTimeEvent(ulong elapsed_time,bool do_dump) {
    count++;
    totalTime += elapsed_time;
    ulong time;

    time=GetTime();

    if(count >= countReportRate        ||
       totalTime > totalTimeReportRate ||
       time-lastReport > timeReportRate) {
      if(do_dump) {
        pprintf(buffer ? (*buffer) : NULL,"%s:rate %f, time per event %g, total time pct %6.2f\n",eventName,
                (double)count / ((time-lastReport)/1000000.0),
                (double)totalTime / count,
                100.0*(double)totalTime / (time-lastReport));
      }
      lastReport=time;
      count = 0UL;
      totalTime = 0UL;
    }
  }
};

#endif
