#include "GlobalStatistics.h"
#include "Logger.h"
#include "Parameters.h"

#include <cassert>

GlobalStatistics * GlobalStatistics::instance = NULL;

GlobalStatistics * GlobalStatistics::getInstance() {
  if ( !instance )
    instance = new GlobalStatistics;
  return instance;
}
void GlobalStatistics::deleteInstance() {
  if ( instance )
    delete instance;
  instance = NULL;
}

GlobalStatistics::GlobalStatistics() :
    myP( Parameters::getInstance()->getP() ),
    stoppedDemes( myP ),
    numConvergedAlleles( new unsigned int[myP] ),
    totalNumConvergedAlleles( 0 ),
    numGenerations( new unsigned int[myP] ),
    totalNumGenerations( 0 ),
    numEpochs( new unsigned int[myP] ),
    totalNumEpochs( 0 ) {
  for ( int i = 0; i < myP; i++ ) {
    numConvergedAlleles[i] = 0;
    numGenerations[i] = 0;
    numEpochs[i] = 0;
  }
}
GlobalStatistics::~ GlobalStatistics() {
  delete[] numConvergedAlleles;
  delete[] numGenerations;
  delete[] numEpochs;
}

bool GlobalStatistics::isDemeStopped( int rank ) const {
  return stoppedDemes.test( rank );
}
void GlobalStatistics::setDemeStopped( int rank, bool value ) {
  stoppedDemes.set( rank, value );
}
unsigned int GlobalStatistics::getNumStoppedDemes() const {
  return stoppedDemes.count();
}

unsigned int GlobalStatistics::getNumConvergedAlleles( int rank ) const {
  assert( rank < myP && rank >= 0 );
  return numConvergedAlleles[rank];
}
void GlobalStatistics::setNumConvergedAlleles( int rank, unsigned int value ) {
  assert( rank < myP && rank >= 0 );
  totalNumConvergedAlleles -= numConvergedAlleles[rank];
  numConvergedAlleles[rank] = value;
  totalNumConvergedAlleles += value;
}
unsigned int GlobalStatistics::getTotalNumConvergedAlleles() const {
  return totalNumConvergedAlleles;
}

unsigned int GlobalStatistics::getNumGenerations( int rank ) const {
  assert( rank < myP && rank >= 0 );
  return numGenerations[rank];
}
void GlobalStatistics::setNumGenerations( int rank, unsigned int value ) {
  assert( rank < myP && rank >= 0 );
  totalNumGenerations -= numGenerations[rank];
  numGenerations[rank] = value;
  totalNumGenerations += value;
}
unsigned int GlobalStatistics::getTotalNumGenerations() const {
  return totalNumGenerations;
}

unsigned int GlobalStatistics::getNumEpochs( int rank ) const {
  assert( rank < myP && rank >= 0 );
  return numEpochs[rank];
}
void GlobalStatistics::setNumEpochs( int rank, unsigned int value ) {
  assert( rank < myP && rank >= 0 );
  totalNumEpochs -= numEpochs[rank];
  numEpochs[rank] = value;
  totalNumEpochs += value;
}
unsigned int GlobalStatistics::getTotalNumEpochs() const {
  return totalNumEpochs;
}
