#pragma once
#include <vector>
#include <string>
#include <unordered_map>

struct StatsCounter
{
    StatsCounter(const std::string &category, const std::string &name);

    inline uint64_t operator++()
    {
        return __sync_fetch_and_add(&m_value, 1);
    }
    inline void operator+=(uint64_t value)
    {
        __sync_fetch_and_add(&m_value, value);
    }

    inline const std::string &getCategory() const { return m_category; }
    inline const std::string &getName() const { return m_name; }
    inline uint64_t getValue() const { return m_value; }
    std::string m_category;
    std::string m_name;
    uint64_t m_value;
};

struct Statistics
{
    static Statistics &getInstance();
    void registerCounter(StatsCounter *counter);
    StatsCounter &getCounter(const std::string &category, const std::string &name);
    std::string getStats();
    void printStats();
    std::unordered_map<std::string, StatsCounter *> m_counters;
    static Statistics *m_instance;
};