#include <iostream>
#include <chrono>
#include <string>
#include "common.hpp"
#define __DEBUG__
std::chrono::_V2::system_clock::time_point start;
std::chrono::_V2::system_clock::time_point end;
long nsTotal;

void Debug_StartMeasure() {
    start = std::chrono::high_resolution_clock::now();
}

void Debug_EndMeasure(const std::string &stuff) {
    end = std::chrono::high_resolution_clock::now();
    int ns = std::chrono::duration_cast<std::chrono::nanoseconds>(end - start).count();
    #ifdef __DEBUG__
    std::cout << "[DEBUG] " << stuff << " took " << (float)(ns)/1000000.0f << " ms"<< std::endl;
    #endif
    nsTotal += ns;
}

void Debug_EndMeasureLoops(const std::string &stuff, int loops) {
    std::cout << "[DEBUG] " << stuff << " took " << (float)(nsTotal)/1000000000.0f << " seconds across " << loops << " loops (" << (float)(nsTotal)/1000000.0f / (float)loops << " ms per cycle)" << std::endl;
    nsTotal = 0;
}

void Debug_Write(const std::string &stuff) {
    #ifdef __DEBUG__
    std::cout << "[DEBUG] " << stuff << std::endl; 
    #endif
}

#if defined(WIN32)
#include <windows.h>
#include <psapi.h>
bool Debug_GetProcessMemory(MemInfo &out) {
    PROCESS_MEMORY_COUNTERS pmc{};
    if (!GetProcessMemoryInfo(GetCurrentProcess(), &pmc, sizeof(pmc))) return false;
    out.resident = pmc.WorkingSetSize;
    out.virtualSize = pmc.PagefileUsage + pmc.WorkingSetSize;
    out.privateBytes = 0;
    return true;
}
#endif
#if !defined(WIN32)
#include <fstream>
#include <string>
#include <unistd.h>
bool Debug_GetProcessMemory(MemInfo &out) {
    out.resident = out.virtualSize = out.privateBytes = 0;
    std::ifstream f("/proc/self/statm");
    if (f) {
        long rss_pages=0, size_pages=0;
        if (f >> size_pages >> rss_pages) {
            long page = sysconf(_SC_PAGESIZE);
            out.resident = (uint64_t)rss_pages * page;
            out.virtualSize = (uint64_t)size_pages * page;
        }
    } else {
        std::ifstream s("/proc/self/status");
        std::string line;
        while (std::getline(s, line)) {
            if (line.rfind("VmRSS:",0)==0) { sscanf(line.c_str(),"VmRSS: %llu kB",&out.resident); out.resident *= 1024; }
            if (line.rfind("VmSize:",0)==0) { sscanf(line.c_str(),"VmSize: %llu kB",&out.virtualSize); out.virtualSize *= 1024; }
        }
    }
    return true;
}
#endif
#if defined(PLAYSTATION2)
bool Debug_GetProcessMemory(MemInfo &out) {
    out.resident = 0;
    out.virtualSize = 32*1024*1024;
    out.privateBytes = 0;
    return true;
}
#endif