#ifndef _STOPWATCH_H
#define _STOPWATCH_H

/*
   CPU timer class.  Simply declare a variable of type Stopwatch
   as early as possible in the program or from wherever you want
   to start timing.  Then use time_elapsed() and display_progress()
   to get info about the CPU time elapsed.

   The timer automatically prints start and end messages when its
   constructor and destructor are called, respectively.  To turns
   these off, compile with the flag '-DQUIET_STOPWATCH'.
*/

#include <iostream>
#include <iomanip>
#include <time.h>

using std::endl;
using std::cout;
using std::setprecision;
using std::fixed;


class Stopwatch 
{

public:

   Stopwatch ();
   ~Stopwatch ();

   clock_t    start_time       () const;
   double     time_elapsed     () const;
   double     time_remaining   (const long t, const long nt) const;
   Stopwatch& reset            ();
   Stopwatch& display_progress (const long t, const long nt);

   friend ostream& operator<< (ostream& out, const Stopwatch& sw);

private:

   clock_t start_time_;

};


Stopwatch::Stopwatch () 
{ 
   start_time_ = clock(); 
   
#  ifndef QUIET_STOPWATCH
      cout << "Stopwatch started: " << fixed << setprecision(3) 
         << time_elapsed() << "s elapsed." << endl; 
#  endif
}


Stopwatch::~Stopwatch () 
{
#  ifndef QUIET_STOPWATCH
      cout << "Stopwatch stopped: " << fixed << setprecision(3) 
         << time_elapsed() << "s elapsed." << endl;
#  endif
}


inline double Stopwatch::time_elapsed () const
{
   return double(clock() - start_time_) * 1e-6;
}


inline clock_t Stopwatch::start_time () const 
{ 
   return start_time_; 
}


inline Stopwatch& Stopwatch::reset () 
{ 
   // Zero the elapsed time.
   start_time_ = clock(); 
   return *this; 
}


inline double Stopwatch::time_remaining (const long t, const long nt) const
{
   // Given a measure of the current time in timesteps or whatever and
   // the total time in the same units, compute the estimated time to finish.
   return double(nt - t) * time_elapsed() / double(t);
}


Stopwatch& Stopwatch::display_progress (const long t, const long nt)
{  
   double t_tot;
   t_tot = double(nt) * time_elapsed() / double(t);
   
   cout << t << "/" << nt << ", T-" << fixed << setprecision(1)
      << time_remaining(t, nt) << "s" << endl;
   return *this;
}  


ostream& operator<< (ostream& out, const Stopwatch& sw)
{
   out << fixed << setprecision(2) << sw.time_elapsed() << "s elapsed.\n";
   return out;
}


#endif
