// Copyright 2021 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "metric.hpp"

#include "metricblob.pb.n.h"

#include "util.hpp"

#include <pb_encode.h>
#include <sys/statvfs.h>

#include <phosphor-logging/log.hpp>

#include <cstdint>
#include <filesystem>
#include <sstream>
#include <string>
#include <string_view>

namespace metric_blob
{

using phosphor::logging::entry;
using phosphor::logging::log;
using level = phosphor::logging::level;

BmcHealthSnapshot::BmcHealthSnapshot() :
    done(false), stringId(0), ticksPerSec(0)
{}

template <typename T>
static constexpr auto pbEncodeStr = [](pb_ostream_t* stream,
                                       const pb_field_iter_t* field,
                                       void* const* arg) noexcept {
    static_assert(sizeof(*std::declval<T>().data()) == sizeof(pb_byte_t));
    const auto& s = *reinterpret_cast<const T*>(*arg);
    return pb_encode_tag_for_field(stream, field) &&
           pb_encode_string(
               stream, reinterpret_cast<const pb_byte_t*>(s.data()), s.size());
};

template <typename T>
static pb_callback_t pbStrEncoder(const T& t) noexcept
{
    return {{.encode = pbEncodeStr<T>}, const_cast<T*>(&t)};
}

template <auto fields, typename T>
static constexpr auto pbEncodeSubs = [](pb_ostream_t* stream,
                                        const pb_field_iter_t* field,
                                        void* const* arg) noexcept {
    for (const auto& sub : *reinterpret_cast<const std::vector<T>*>(*arg))
    {
        if (!pb_encode_tag_for_field(stream, field) ||
            !pb_encode_submessage(stream, fields, &sub))
        {
            return false;
        }
    }
    return true;
};

template <auto fields, typename T>
static pb_callback_t pbSubsEncoder(const std::vector<T>& t)
{
    return {{.encode = pbEncodeSubs<fields, T>},
            const_cast<std::vector<T>*>(&t)};
}

struct ProcStatEntry
{
    std::string cmdline;
    std::string tcomm;
    float utime;
    float stime;

    // Processes with the longest utime + stime are ranked first.
    // Tie breaking is done with cmdline then tcomm.
    bool operator<(const ProcStatEntry& other) const
    {
        const float negTime = -(utime + stime);
        const float negOtherTime = -(other.utime + other.stime);
        return std::tie(negTime, cmdline, tcomm) <
               std::tie(negOtherTime, other.cmdline, other.tcomm);
    }
};

static bmcmetrics_metricproto_BmcProcStatMetric getProcStatMetric(
    BmcHealthSnapshot& obj, long ticksPerSec,
    std::vector<bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat>& procs,
    bool& use) noexcept
{
    if (ticksPerSec == 0)
    {
        return {};
    }
    constexpr std::string_view procPath = "/proc/";

    std::vector<ProcStatEntry> entries;

    for (const auto& procEntry : std::filesystem::directory_iterator(procPath))
    {
        const std::string& path = procEntry.path();
        int pid = -1;
        if (isNumericPath(path, pid))
        {
            ProcStatEntry entry;

            try
            {
                entry.cmdline = getCmdLine(pid);
                TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec);
                entry.tcomm = t.tcomm;
                entry.utime = t.utime;
                entry.stime = t.stime;

                entries.push_back(entry);
            }
            catch (const std::exception& e)
            {
                log<level::ERR>("Could not obtain process stats");
            }
        }
    }

    std::sort(entries.begin(), entries.end());

    bool isOthers = false;
    ProcStatEntry others;
    others.cmdline = "(Others)";
    others.utime = others.stime = 0;

    // Only show this many processes and aggregate all remaining ones into
    // "others" in order to keep the size of the snapshot reasonably small.
    // With 10 process stat entries and 10 FD count entries, the size of the
    // snapshot reaches around 1.5KiB. This is non-trivial, and we have to set
    // the collection interval long enough so as not to over-stress the IPMI
    // interface and the data collection service. The value of 10 is chosen
    // empirically, it might be subject to adjustments when the system is
    // launched later.
    constexpr int topN = 10;

    for (size_t i = 0; i < entries.size(); ++i)
    {
        if (i >= topN)
        {
            isOthers = true;
        }

        const ProcStatEntry& entry = entries[i];

        if (isOthers)
        {
            others.utime += entry.utime;
            others.stime += entry.stime;
        }
        else
        {
            std::string fullCmdline = entry.cmdline;
            if (entry.tcomm.size() > 0)
            {
                fullCmdline += " ";
                fullCmdline += entry.tcomm;
            }
            procs.emplace_back(
                bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat{
                    .sidx_cmdline = obj.getStringID(fullCmdline),
                    .utime = entry.utime,
                    .stime = entry.stime,
                });
        }
    }

    if (isOthers)
    {
        procs.emplace_back(bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat{
            .sidx_cmdline = obj.getStringID(others.cmdline),
            .utime = others.utime,
            .stime = others.stime,

        });
    }

    use = true;
    return bmcmetrics_metricproto_BmcProcStatMetric{
        .stats = pbSubsEncoder<
            bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat_fields>(procs),
    };
}

int getFdCount(int pid)
{
    const std::string& fdPath = "/proc/" + std::to_string(pid) + "/fd";
    return std::distance(std::filesystem::directory_iterator(fdPath),
                         std::filesystem::directory_iterator{});
}

struct FdStatEntry
{
    int fdCount;
    std::string cmdline;
    std::string tcomm;

    // Processes with the largest fdCount goes first.
    // Tie-breaking using cmdline then tcomm.
    bool operator<(const FdStatEntry& other) const
    {
        const int negFdCount = -fdCount;
        const int negOtherFdCount = -other.fdCount;
        return std::tie(negFdCount, cmdline, tcomm) <
               std::tie(negOtherFdCount, other.cmdline, other.tcomm);
    }
};

static bmcmetrics_metricproto_BmcFdStatMetric getFdStatMetric(
    BmcHealthSnapshot& obj, long ticksPerSec,
    std::vector<bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat>& fds,
    bool& use) noexcept
{
    if (ticksPerSec == 0)
    {
        return {};
    }

    // Sort by fd count, no tie-breaking
    std::vector<FdStatEntry> entries;

    const std::string_view procPath = "/proc/";
    for (const auto& procEntry : std::filesystem::directory_iterator(procPath))
    {
        const std::string& path = procEntry.path();
        int pid = 0;
        FdStatEntry entry;
        if (isNumericPath(path, pid))
        {
            try
            {
                entry.fdCount = getFdCount(pid);
                TcommUtimeStime t = getTcommUtimeStime(pid, ticksPerSec);
                entry.cmdline = getCmdLine(pid);
                entry.tcomm = t.tcomm;
                entries.push_back(entry);
            }
            catch (const std::exception& e)
            {
                log<level::ERR>("Could not get file descriptor stats");
            }
        }
    }

    std::sort(entries.begin(), entries.end());

    bool isOthers = false;

    // Only report the detailed fd count and cmdline for the top 10 entries,
    // and collapse all others into "others".
    constexpr int topN = 10;

    FdStatEntry others;
    others.cmdline = "(Others)";
    others.fdCount = 0;

    for (size_t i = 0; i < entries.size(); ++i)
    {
        if (i >= topN)
        {
            isOthers = true;
        }

        const FdStatEntry& entry = entries[i];
        if (isOthers)
        {
            others.fdCount += entry.fdCount;
        }
        else
        {
            std::string fullCmdline = entry.cmdline;
            if (entry.tcomm.size() > 0)
            {
                fullCmdline += " ";
                fullCmdline += entry.tcomm;
            }
            fds.emplace_back(bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat{
                .sidx_cmdline = obj.getStringID(fullCmdline),
                .fd_count = entry.fdCount,
            });
        }
    }

    if (isOthers)
    {
        fds.emplace_back(bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat{
            .sidx_cmdline = obj.getStringID(others.cmdline),
            .fd_count = others.fdCount,
        });
    }

    use = true;
    return bmcmetrics_metricproto_BmcFdStatMetric{
        .stats = pbSubsEncoder<
            bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat_fields>(fds),
    };
}

static bmcmetrics_metricproto_BmcECCMetric getECCMetric(bool& use) noexcept
{
    EccCounts eccCounts;
    use = getECCErrorCounts(eccCounts);
    if (!use)
    {
        return {};
    }
    return bmcmetrics_metricproto_BmcECCMetric{
        .correctable_error_count = eccCounts.correctableErrCount,
        .uncorrectable_error_count = eccCounts.uncorrectableErrCount,
    };
}

static bmcmetrics_metricproto_BmcMemoryMetric getMemMetric() noexcept
{
    bmcmetrics_metricproto_BmcMemoryMetric ret = {};
    auto data = readFileThenGrepIntoString("/proc/meminfo");
    int value;
    if (parseMeminfoValue(data, "MemAvailable:", value))
    {
        ret.mem_available = value;
    }
    if (parseMeminfoValue(data, "Slab:", value))
    {
        ret.slab = value;
    }

    if (parseMeminfoValue(data, "KernelStack:", value))
    {
        ret.kernel_stack = value;
    }
    return ret;
}

static bmcmetrics_metricproto_BmcUptimeMetric
    getUptimeMetric(bool& use) noexcept
{
    bmcmetrics_metricproto_BmcUptimeMetric ret = {};

    double uptime = 0;
    {
        auto data = readFileThenGrepIntoString("/proc/uptime");
        double idleProcessTime = 0;
        if (!parseProcUptime(data, uptime, idleProcessTime))
        {
            log<level::ERR>("Error parsing /proc/uptime");
            return ret;
        }
        ret.uptime = uptime;
        ret.idle_process_time = idleProcessTime;
    }

    BootTimesMonotonic btm;
    if (!getBootTimesMonotonic(btm))
    {
        log<level::ERR>("Could not get boot time");
        return ret;
    }
    if (btm.firmwareTime == 0 && btm.powerOnSecCounterTime != 0)
    {
        ret.firmware_boot_time_sec =
            static_cast<double>(btm.powerOnSecCounterTime) - uptime;
    }
    else
    {
        ret.firmware_boot_time_sec =
            static_cast<double>(btm.firmwareTime - btm.loaderTime) / 1e6;
    }
    ret.loader_boot_time_sec = static_cast<double>(btm.loaderTime) / 1e6;
    if (btm.initrdTime != 0)
    {
        ret.kernel_boot_time_sec = static_cast<double>(btm.initrdTime) / 1e6;
        ret.initrd_boot_time_sec =
            static_cast<double>(btm.userspaceTime - btm.initrdTime) / 1e6;
        ret.userspace_boot_time_sec =
            static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6;
    }
    else
    {
        ret.kernel_boot_time_sec = static_cast<double>(btm.userspaceTime) / 1e6;
        ret.initrd_boot_time_sec = 0;
        ret.userspace_boot_time_sec =
            static_cast<double>(btm.finishTime - btm.userspaceTime) / 1e6;
    }

    use = true;
    return ret;
}

static bmcmetrics_metricproto_BmcDiskSpaceMetric
    getStorageMetric(bool& use) noexcept
{
    bmcmetrics_metricproto_BmcDiskSpaceMetric ret = {};
    struct statvfs fiData;
    if (statvfs("/", &fiData) < 0)
    {
        log<level::ERR>("Could not call statvfs");
    }
    else
    {
        ret.rwfs_kib_available = (fiData.f_bsize * fiData.f_bfree) / 1024;
        use = true;
    }
    return ret;
}

void BmcHealthSnapshot::doWork()
{
    // The next metrics require a sane ticks_per_sec value, typically 100 on
    // the BMC. In the very rare circumstance when it's 0, exit early and return
    // a partially complete snapshot (no process).
    ticksPerSec = getTicksPerSec();

    static constexpr auto stcb = [](pb_ostream_t* stream,
                                    const pb_field_t* field,
                                    void* const* arg) noexcept {
        auto& self = *reinterpret_cast<BmcHealthSnapshot*>(*arg);
        std::vector<std::string_view> strs(self.stringTable.size());
        for (const auto& [str, i] : self.stringTable)
        {
            strs[i] = str;
        }
        for (auto& str : strs)
        {
            bmcmetrics_metricproto_BmcStringTable_StringEntry msg = {
                .value = pbStrEncoder(str),
            };
            if (!pb_encode_tag_for_field(stream, field) ||
                !pb_encode_submessage(
                    stream,
                    bmcmetrics_metricproto_BmcStringTable_StringEntry_fields,
                    &msg))
            {
                return false;
            }
        }
        return true;
    };
    std::vector<bmcmetrics_metricproto_BmcProcStatMetric_BmcProcStat> procs;
    std::vector<bmcmetrics_metricproto_BmcFdStatMetric_BmcFdStat> fds;
    bmcmetrics_metricproto_BmcMetricSnapshot snapshot = {
        .has_string_table = true,
        .string_table =
            {
                .entries = {{.encode = stcb}, this},
            },
        .has_memory_metric = true,
        .memory_metric = getMemMetric(),
        .has_uptime_metric = false,
        .uptime_metric = getUptimeMetric(snapshot.has_uptime_metric),
        .has_storage_space_metric = false,
        .storage_space_metric =
            getStorageMetric(snapshot.has_storage_space_metric),
        .has_procstat_metric = false,
        .procstat_metric = getProcStatMetric(*this, ticksPerSec, procs,
                                             snapshot.has_procstat_metric),
        .has_fdstat_metric = false,
        .fdstat_metric = getFdStatMetric(*this, ticksPerSec, fds,
                                         snapshot.has_fdstat_metric),
        .has_ecc_metric = false,
        .ecc_metric = getECCMetric(snapshot.has_ecc_metric),
    };
    pb_ostream_t nost = {};
    if (!pb_encode(&nost, bmcmetrics_metricproto_BmcMetricSnapshot_fields,
                   &snapshot))
    {
        auto msg = std::format("Getting pb size: {}", PB_GET_ERROR(&nost));
        log<level::ERR>(msg.c_str());
        return;
    }
    pbDump.resize(nost.bytes_written);
    auto ost = pb_ostream_from_buffer(
        reinterpret_cast<pb_byte_t*>(pbDump.data()), pbDump.size());
    if (!pb_encode(&ost, bmcmetrics_metricproto_BmcMetricSnapshot_fields,
                   &snapshot))
    {
        auto msg = std::format("Writing pb msg: {}", PB_GET_ERROR(&ost));
        log<level::ERR>(msg.c_str());
        return;
    }
    done = true;
}

// BmcBlobSessionStat (9) but passing meta as reference instead of pointer,
// since the metadata must not be null at this point.
bool BmcHealthSnapshot::stat(blobs::BlobMeta& meta)
{
    if (!done)
    {
        // Bits 8~15 are blob-specific state flags.
        // For this blob, bit 8 is set when metric collection is still in
        // progress.
        meta.blobState |= (1 << 8);
    }
    else
    {
        meta.blobState = 0;
        meta.blobState = blobs::StateFlags::open_read;
        meta.size = pbDump.size();
    }
    return true;
}

std::string_view BmcHealthSnapshot::read(uint32_t offset,
                                         uint32_t requestedSize)
{
    uint32_t size = static_cast<uint32_t>(pbDump.size());
    if (offset >= size)
    {
        return {};
    }
    return std::string_view(pbDump.data() + offset,
                            std::min(requestedSize, size - offset));
}

int BmcHealthSnapshot::getStringID(const std::string_view s)
{
    int ret = 0;
    auto itr = stringTable.find(s.data());
    if (itr == stringTable.end())
    {
        stringTable[s.data()] = stringId;
        ret = stringId;
        ++stringId;
    }
    else
    {
        ret = itr->second;
    }
    return ret;
}

} // namespace metric_blob
