#pragma once

#include <assert.h>

#ifdef _WIN32
#define NOMINMAX
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#else
#include <sys/time.h>
#include <sys/resource.h>
#endif

class Stopwatch
{
#ifdef _WIN32
  typedef long long TimeUnit;
#else
  typedef struct timeval TimeUnit;
#endif

public:
  Stopwatch()
    : m_total(0.)
#ifdef _DEBUG
    , m_started(false)
#endif
  {}

  void start() {
#ifdef _DEBUG
    assert(!m_started);
    m_started = true;
#endif
#ifdef _WIN32
    QueryPerformanceCounter((LARGE_INTEGER *) &m_begin);
#else
    gettimeofday(&m_begin, NULL);  
#endif
  }

  void stop() {
    double timeElapsed = getTimeElapsed();
    m_total += timeElapsed;
#ifdef _DEBUG
    assert(m_started);
    m_started = false;
#endif
  }

  double getTimeElapsed() const {
#ifdef _DEBUG
    assert(m_started);
#endif
#ifdef _WIN32
    TimeUnit end;
    long long freq;
    QueryPerformanceCounter((LARGE_INTEGER *) &end);
    QueryPerformanceFrequency((LARGE_INTEGER *) &freq);    
    return ((double) (end - (m_begin))) / freq; 
#else
    TimeUnit end;
    gettimeofday(&end, NULL);      
    return (1.000000 * (end.tv_sec  - c->tv_sec ) + 0.000001 * (end.tv_usec - c->tv_usec));
#endif
  }

  double totalTimeElapsed() const {
#ifdef _DEBUG
    assert(!m_started);
#endif
    return m_total;
  }

private:
  double m_total;
  TimeUnit m_begin;

#ifdef _DEBUG
  bool m_started;
#endif
};
