#pragma once

#include "dCommonVars.h"
#include <vector>
#include <map>
#include <unordered_map>
#include <chrono>

#define MAX_MEASURMENT_POINTS 1024

enum class MetricVariable : int32_t
{
    GameLoop,
    PacketHandling,
    UpdateEntities,
    UpdateSpawners,
    Physics,
    UpdateReplica,
    Ghosting,
    CPUTime,
    Sleep,
    Frame,
};

struct Metric
{
    int64_t measurements[MAX_MEASURMENT_POINTS] = {};
    size_t measurementIndex = 0;
    size_t measurementSize = 0;
    int64_t max = -1;
    int64_t min = -1;
    int64_t average = 0;
    std::chrono::time_point<std::chrono::high_resolution_clock> activeMeasurement;
};

class Metrics
{
public:
    ~Metrics();

    static void AddMeasurement(MetricVariable variable, int64_t value);
    static void AddMeasurement(Metric* metric, int64_t value);
    static const Metric* GetMetric(MetricVariable variable);
    static void StartMeasurement(MetricVariable variable);
    static void EndMeasurement(MetricVariable variable);
    static float ToMiliseconds(int64_t nanoseconds);
    static std::string MetricVariableToString(MetricVariable variable);
    static const std::vector<MetricVariable>& GetAllMetrics();

    static size_t GetPeakRSS();
    static size_t GetCurrentRSS();
    static size_t GetProcessID();

    static void Clear();

private:
    Metrics();

    static std::unordered_map<MetricVariable, Metric*> m_Metrics;
    static std::vector<MetricVariable> m_Variables;
};