#include <iostream>
#include <iomanip>
#include <windows.h>
#include "stop-watch.h"

using namespace std;

StopWatch::StopWatch() : running(false), total_time(0) {
    LARGE_INTEGER performanceFrequency;
    if (QueryPerformanceFrequency(&performanceFrequency) == 0) {
        printError();
    }
    f = double(performanceFrequency.QuadPart);
}

void StopWatch::start() {
    if (!running) {
        running = true;
        start_time = getExecutionTime();
    }
}

void StopWatch::stop() {
    if (running) {
        running = false;
        total_time = getExecutionTime() - start_time;
    }
}

long long StopWatch::getExecutionTime() const {
    LARGE_INTEGER performanceCount;
    if (QueryPerformanceCounter(&performanceCount) == 0) {
        printError();
    }
    return performanceCount.QuadPart;
}

void StopWatch::printError() const {
    LPTSTR lpMsgBuf = 0;
    FormatMessage(
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
        NULL,
        GetLastError(),
        MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
        lpMsgBuf,
        0,
        NULL
        );
    cerr << lpMsgBuf << endl;
    LocalFree(lpMsgBuf);
}

ostream& operator<<(ostream& o, const StopWatch& sw) {
    long long res = sw.running ? sw.getExecutionTime() - sw.start_time : sw.total_time;
    return o << fixed << setprecision(2) << res / sw.f << " sec";
}
