#include "HumanReadableBytes.h"
#include <iomanip>
#include <sstream>

using namespace std;

namespace {

struct scale {
    int64_t scale;
    const char* prefix;
};

void fmt(std::ostringstream &o, double d)
{
    ;
    if (d < 10.0)
    {
        o << fixed << setprecision(2) << d;
        //return std::format("{:.3g}", d);
    }
    else if (d < 100.0)
    {
        o << fixed << setprecision(1) << d;
        //return std::format("{:.3g}", d);
    }
    else
    {
        o << fixed << setprecision(0) << d;
    }
}

}

std::string HumanReadableBytes(uint64_t bytes)
{
    static scale scales[] = {
                             { 1024ll * 1024 * 1024 * 1024, "Ti" },
                             { 1024ll * 1024 * 1024, "Gi" },
                             { 1024ll * 1024, "Mi" },
                             { 1024ll, "ki" },
                             };

    std::ostringstream out;
    for (unsigned int i = 0; i < (sizeof(scales) / sizeof(scale)); ++i)
    {
        if (bytes >= scales[i].scale)
        {
            fmt(out, bytes / double(scales[i].scale));
            out << " " << scales[i].prefix << "B";
            return out.str();
        }
    }
    out << bytes << " B";
    return out.str();
}
