#include "os.h"
#include "tile/base/logging.h"
#include "tile/base/string.h"

#include <iostream>
#include <map>
#include <unistd.h>

namespace tile {

static std::map<std::string, std::string>
ReadProcPidStatus(uint64_t pid)
{
    std::map<std::string, std::string> res;
    std::string path = "/proc/" + std::to_string(pid) + "/status";
    std::ifstream ifs(path);
    if (!ifs.is_open()) {
        TILE_LOG_ERROR_EVERY_SECOND("Open file [{}] failed.", path);
        return res;
    }

    std::string line;
    while (std::getline(ifs, line)) {
        auto kv = tile::Split(line, ":");
        if (kv.size() < 2) { continue; }

        auto params = tile::Split(tile::Trim(kv[1]), " ");
        if (!params.empty()) { res[kv[0]] = params[0]; }
    }
    return res;
}

uint64_t
OperatorSystem::MyPid()
{
    return getpid();
}

uint64_t
OperatorSystem::MyPPid()
{
    return getppid();
}

int64_t
OperatorSystem::GetMemoryInfo(Slice key, uint64_t pid)
{
    static std::vector<std::string> kFilters = {
        "VmPeak",   "VmSize", "VmLck", "VmHWM", "VmRSS", "RssAnon", "RssFile",
        "RssShmem", "VmData", "VmStk", "VmExe", "VmLib", "VmPTE",
    };
    if (std::find(kFilters.begin(), kFilters.end(), key) == kFilters.end()) { return -1; }
    auto m    = ReadProcPidStatus(pid);
    auto iter = m.find(key);
    if (iter == m.end()) { return -1; }
    return tile::TryParse<int64_t>(iter->second).value_or(-1);
}

}// namespace tile
