#include "StoppingConditions.h"

#include <cstdio>
#include <ctime>

StoppingConditions::StoppingConditions( const SgEngine * const e ) :
    engine( e ),
    startClock( std::clock() ) {
  /* Empty */
}

unsigned StoppingConditions::getCpuTime() const {
  return static_cast<unsigned>(( std::clock() - startClock ) / CLOCKS_PER_SEC );
}

void StoppingConditions::add( ConditionType type, unsigned parameter ) {
  Condition condition = { type, parameter };
  conditions.push_back( condition );
}

bool StoppingConditions::pollDisjunctive( bool verbose ) const {
  bool result = false;
  for ( VectorType::const_iterator it = conditions.begin(), last = conditions.end(); it != last; it++ )
    result = result || poll( it->type, it->parameter, verbose );
  return result;
}

bool StoppingConditions::pollConjunctive( bool verbose ) const {
  bool result = true;
  for ( VectorType::const_iterator it = conditions.begin(), last = conditions.end(); it != last; it++ )
    result = result && poll( it->type, it->parameter, verbose );
  return result;
}

inline bool StoppingConditions::poll( ConditionType type, unsigned parameter, bool verbose ) const {
  unsigned lhs;
  char *typeString;
  switch ( type ) {
    case GENERATIONS:
      lhs = engine->getGenerationCount();
      typeString = "number of generations";
      break;
    case CPU_TIME:
      lhs = this->getCpuTime();
      typeString = "CPU time";
      break;
    case CONVERGED_ALLELES:
      lhs = engine->getPopulation()->getNumberOfConvergedAlleles();
      typeString = "converged alleles";
      break;
  }
  if ( lhs >= parameter ) {
    if ( verbose ) std::printf( "Stopping condition reached :: %s %u >= %u\n", typeString, lhs, parameter );
    return true;
  } else return false;
}
