#include "runnerDefine.icc"

#include <signal.h>
#include <sys/types.h>
#include <unistd.h>

#include <iostream>

#include "ShmObject.hh"
#include "RunMonitorShm.hh"
#include "UtlArguments.hh"

using namespace std;

bool continueJob=true;

void signalHandler(int signal) {
  std::cerr << "Process " << getpid() << " received signal "
            << signal << std::endl;
  continueJob=false;
}

int main(int argc, const char *argv[]) {
  UtlArguments argh(argc,argv);
  const bool verbose(argh.option('v',true,"Verbose display"));
  const unsigned sleepSecs(argh.optionArgument('s',1,"Sleep period (secs), 0 = do once"));
  if(argh.help()) return 0;

  signal(SIGINT,signalHandler);
  signal(SIGTERM,signalHandler);

  ShmObject<RunMonitorShm> shmRunMonitor(RunMonitorShm::shmKey);
  RunMonitorShm *q(shmRunMonitor.payload());
  if(q==0) return 1;
  RunCount *p(&(q->runCount()));
  if(p==0) return 1;

  UtlTime timeOld(true);

#ifndef DAQ_ILC_TIMING
  unsigned eventsOld[2];
  unsigned eventsNew[2];
  unsigned eventsRun(0);
  //eventsOld[0]=p->count(RcdHeader::trigger);
  eventsOld[0]=p->triggers();
  eventsOld[1]=p->count(RcdHeader::event);

  double deltaTime[5];
  double rate[7];
  for(unsigned i(0);i<7;i++) rate[i]=0.0;

  while(continueJob) {
    UtlTime timeNew(true);
    double delta((timeNew-timeOld).deltaTime());

    //if(delta>3.0) {
    if(delta>0.1) {
      //eventsNew[0]=p->count(RcdHeader::trigger);
      eventsNew[0]=p->triggers();
      eventsNew[1]=p->count();

      rate[5]=0.5+(eventsNew[0]-eventsOld[0])/delta;
      rate[6]=0.5+(eventsNew[1]-eventsOld[1])/delta;

      timeOld=timeNew;
      eventsOld[0]=eventsNew[0];
      eventsOld[1]=eventsNew[1];
    }

    for(unsigned i(0);i<5;i++) {
      deltaTime[i]=(p->header(6).recordTime()-p->header(i).recordTime()).deltaTime();
      if(deltaTime[i]>0.1) {
	rate[i]=0.5+p->count(RcdHeader::event,i)/deltaTime[i];
      }
    }

    UtlTime runStart=p->header(2).recordTime();
    double derun((p->header(6).recordTime()-runStart).deltaTime());

    if(derun>0.1) {
      eventsRun=p->count(RcdHeader::event,2);
      rate[2]=0.5+eventsRun/derun;
    }

    std::cout << "Time now = " << timeNew << std::endl;

    //p->print(std::cout);
    
    std::string tag[5]={" Job "," Seq "," Run "," Cfg "," Acq "};

    for(unsigned i(0);i<5;i++) {
      if(verbose || i==2) { // Only do run stats if not verbose
	if(p->counter(i).totalCount()>0) {

	  if(verbose) {
	    p->header(i).print(std::cout,tag[i]);
	    p->counter(i).print(std::cout,tag[i]);

	    std::cout << tag[i] << "Time =  "
		      << std::setw(6) << (unsigned)deltaTime[i] << " sec"
		      << ", averaged event rate = "
		      << std::setw(6) << (unsigned)rate[i] 
		      << " Hz" << std::endl << std::endl;

	  } else {
	    std::cout << std::endl;
	    std::cout << " Number of Configurations      =    "
		      << p->counter(i).count(RcdHeader::configurationStart)
		      << std::endl << std::endl;
	    std::cout << " Number of Events in Run       =    "
		      << p->counter(i).count(RcdHeader::event)
		      << std::endl;
	    std::cout << " Number of Events in Config    =    "
		      << p->counter(3).count(RcdHeader::event)
		      << std::endl;
	    std::cout << " Running time since Run Start  =    "
		      << (unsigned)(deltaTime[i]/60.0) << " min"
		      << std::endl;
	    std::cout << " Averaged event rate in Run    =    "
		      << (unsigned)rate[i] 
		      << " Hz" << std::endl;
	    std::cout << " Averaged event rate in Config =    "
		      << (unsigned)rate[i+1] 
		      << " Hz" << std::endl;
	  }
	}
      }
    }

    if(verbose) {
      p->header(5).print(std::cout," Last ");
      if(p->header(5)!=p->header(6))
	p->header(6).print(std::cout," Last ");
      std::cout << "                             Time now = " << timeNew << std::endl;
      
      std::cout << std::endl 
		<< " Trigger, event: instantaneous rates = "
		<< std::setw(6) << (unsigned)rate[5] 
		<< " Hz,  " << std::setw(6) << (unsigned)rate[6]
		<< " Hz" << std::endl << std::endl;

    } else {
      std::cout << std::endl 
		<< " Trigger rate                  = "
		<< std::setw(6) << (unsigned)rate[5] 
		<< " Hz" << std::endl << std::endl;
    }

    if(sleepSecs>0) sleep(sleepSecs);
    else continueJob=false;
  }

#else
  unsigned bunchTrainsOld;
  unsigned bunchTrainsNew;
  unsigned bunchTrainsRun(0);
  bunchTrainsOld=p->count(RcdHeader::bunchTrain);

  double deltaTime[4];
  double rate[6];
  for(unsigned i(0);i<6;i++) rate[i]=0.0;

  while(continueJob) {
    UtlTime timeNew(true);
    double delta((timeNew-timeOld).deltaTime());

    //if(delta>3.0) {
    if(delta>0.1) {
      bunchTrainsNew=p->count(RcdHeader::bunchTrain);

      rate[5]=0.5+(bunchTrainsNew-bunchTrainsOld)/delta;

      timeOld=timeNew;
      bunchTrainsOld=bunchTrainsNew;
    }

    for(unsigned i(0);i<4;i++) {
      deltaTime[i]=(p->header(6).recordTime()-p->header(i).recordTime()).deltaTime();
      if(deltaTime[i]>0.1) {
	rate[i]=0.5+p->count(RcdHeader::bunchTrain,i)/deltaTime[i];
      }
    }

    UtlTime runStart=p->header(2).recordTime();
    double derun((p->header(6).recordTime()-runStart).deltaTime());

    if(derun>0.1) {
      bunchTrainsRun=p->count(RcdHeader::bunchTrain,2);
      rate[2]=0.5+bunchTrainsRun/derun;
    }

    std::cout << "Time now = " << timeNew << std::endl;

    //p->print(std::cout);
    
    std::string tag[4]={" Job "," Seq "," Run "," Cfg "};

    for(unsigned i(0);i<4;i++) {
      if(verbose || i==2) { // Only do run stats if not verbose
	if(p->counter(i).totalCount()>0) {

	  if(verbose) {
	    p->header(i).print(std::cout,tag[i]);
	    p->counter(i).print(std::cout,tag[i]);

	    std::cout << tag[i] << "Time =  "
		      << std::setw(6) << (unsigned)deltaTime[i] << " sec"
		      << ", averaged bunch train rate = "
		      << std::setw(6) << (unsigned)rate[i] 
		      << " Hz" << std::endl << std::endl;

	  } else {
	    std::cout << std::endl;
	    std::cout << " Number of Configurations         =    "
		      << p->counter(i).count(RcdHeader::configurationStart)
		      << std::endl << std::endl;
	    std::cout << " Number of Bunch trains in Run    =    "
		      << p->counter(i).count(RcdHeader::bunchTrain)
		      << std::endl;
	    std::cout << " Number of Bunch trains in Config =    "
		      << p->counter(3).count(RcdHeader::bunchTrain)
		      << std::endl;
	    std::cout << " Running time since Run Start     =    "
		      << (unsigned)(deltaTime[i]/60.0) << " min"
		      << std::endl;
	    std::cout << " Averaged Bunch train rate in Run    =    "
		      << (unsigned)rate[i] 
		      << " Hz" << std::endl;
	    std::cout << " Averaged Bunch Train rate in Config =    "
		      << (unsigned)rate[i+1] 
		      << " Hz" << std::endl;
	  }
	}
      }
    }

    if(verbose) {
      p->header(5).print(std::cout," Last ");
      if(p->header(5)!=p->header(6))
	p->header(6).print(std::cout," Last ");
      std::cout << "                             Time now = " << timeNew << std::endl;
      
      std::cout << std::endl 
		<< " Bunch train: instantaneous rate = "
		<< std::setw(6) << (unsigned)rate[5] 
		<< " Hz" << std::endl << std::endl;

    } else {
      std::cout << std::endl 
		<< " Bunch train rate                  = "
		<< std::setw(6) << (unsigned)rate[5] 
		<< " Hz" << std::endl << std::endl;
    }

    if(sleepSecs>0) sleep(sleepSecs);
    else continueJob=false;
  }
#endif

  return 0;
}
