#include "Statistics.h"
#include "Logger.h"

#include <cstddef>
#include <mpi.h>

Statistics * Statistics::instance = NULL;

Statistics * Statistics::getInstance() {
  if ( !instance )
    instance = new Statistics;
  return instance;
}

void Statistics::deleteInstance() {
  if ( instance )
    delete instance;
  instance = NULL;
}

Statistics::Statistics() :
    startTime( 0.0 ),
    timerStarted( false ),
    numGenerationsTotal( 0 ),
    numGenerationsEpoch( 0 ),
    numEpochs( 0 ),
    numConvergedAlleles( 0 ),
    globalStopSent( false ),
    executionFinished( false ) { /* Empty. */ }

void Statistics::startTimer() {
  startTime = MPI_Wtime();
  timerStarted = true;
}

unsigned int Statistics::getCpuTime() const {
  if ( timerStarted )
    return static_cast<unsigned int>( MPI_Wtime() - startTime );
  else
    return 0u;
}

unsigned int Statistics::getNumGenerationsTotal() const {
  return numGenerationsTotal;
}
void Statistics::setNumGenerationsTotal( unsigned int value ) {
  numGenerationsTotal = value;
}

unsigned int Statistics::getNumGenerationsEpoch() const {
  return numGenerationsEpoch;
}
void Statistics::setNumGenerationsEpoch( unsigned int value ) {
  numGenerationsEpoch = value;
}

unsigned int Statistics::getNumEpochs() const {
  return numEpochs;
}
void Statistics::setNumEpochs( unsigned int value ) {
  numEpochs = value;
}

unsigned int Statistics::getNumConvergedAlleles() const {
  return numConvergedAlleles;
}
void Statistics::setNumConvergedAlleles( unsigned int value ) {
  numConvergedAlleles = value;
}

bool Statistics::isGlobalStopSent() const {
  return globalStopSent;
}
void Statistics::setGlobalStopSent( bool value ) {
  globalStopSent = value;
}

bool Statistics::isExecutionFinished() const {
  return executionFinished;
}
void Statistics::setExecutionFinished( bool value ) {
  executionFinished = value;
}

unsigned int Statistics::adjustNumConvergedAlleles( int value ) {
  numConvergedAlleles += value;
  return numConvergedAlleles;
}

unsigned int Statistics::adjustNumGenerations( int value ) {
  numGenerationsTotal += value;
  numGenerationsEpoch += value;
  return numGenerationsTotal;
}

void Statistics::startNewEpoch() {
  LOG( Logger::LOGLEVEL_MEDIUM, "startNewEpoch\tEpoch #%u had %u generations", numEpochs, numGenerationsEpoch );
  numGenerationsEpoch = 0;
  numEpochs++;
}
