#include "health_metric.hpp"

#include <phosphor-logging/lg2.hpp>

#include <numeric>
#include <unordered_map>

PHOSPHOR_LOG2_USING;

namespace phosphor::health::metric
{

using association_t = std::tuple<std::string, std::string, std::string>;

auto HealthMetric::getPath(SubType subType) -> std::string
{
    std::string path;
    switch (subType)
    {
        case SubType::cpuTotal:
        {
            return std::string(BmcPath) + "/" + PathIntf::total_cpu;
        }
        case SubType::cpuKernel:
        {
            return std::string(BmcPath) + "/" + PathIntf::kernel_cpu;
        }
        case SubType::cpuUser:
        {
            return std::string(BmcPath) + "/" + PathIntf::user_cpu;
        }
        case SubType::memoryAvailable:
        {
            return std::string(BmcPath) + "/" + PathIntf::available_memory;
        }
        case SubType::memoryBufferedAndCached:
        {
            return std::string(BmcPath) + "/" +
                   PathIntf::buffered_and_cached_memory;
        }
        case SubType::memoryFree:
        {
            return std::string(BmcPath) + "/" + PathIntf::free_memory;
        }
        case SubType::memoryShared:
        {
            return std::string(BmcPath) + "/" + PathIntf::shared_memory;
        }
        case SubType::memoryTotal:
        {
            return std::string(BmcPath) + "/" + PathIntf::total_memory;
        }
        case SubType::storageReadWrite:
        {
            return std::string(BmcPath) + "/" + PathIntf::read_write_storage;
        }
        case SubType::storageTmp:
        {
            return std::string(BmcPath) + "/" + PathIntf::tmp_storage;
        }
        default:
        {
            error("Invalid Memory metric {TYPE}", "TYPE",
                  std::to_underlying(subType));
            return "";
        }
    }
}

void HealthMetric::initProperties()
{
    switch (config.subType)
    {
        case SubType::cpuTotal:
        case SubType::cpuKernel:
        case SubType::cpuUser:
        {
            ValueIntf::unit(ValueIntf::Unit::Percent, true);
            ValueIntf::minValue(0.0, true);
            ValueIntf::maxValue(100.0, true);
            break;
        }
        case SubType::memoryAvailable:
        case SubType::memoryBufferedAndCached:
        case SubType::memoryFree:
        case SubType::memoryShared:
        case SubType::memoryTotal:
        case SubType::storageReadWrite:
        default:
        {
            ValueIntf::unit(ValueIntf::Unit::Bytes, true);
            ValueIntf::minValue(0.0, true);
        }
    }
    ValueIntf::value(std::numeric_limits<double>::quiet_NaN(), true);

    using bound_map_t = std::map<ThresholdIntf::Bound, double>;
    std::map<ThresholdIntf::Type, bound_map_t> thresholds;
    for (const auto& [key, value] : config.thresholds)
    {
        auto type = std::get<ThresholdIntf::Type>(key);
        auto bound = std::get<ThresholdIntf::Bound>(key);
        auto threshold = thresholds.find(type);
        if (threshold == thresholds.end())
        {
            bound_map_t bounds;
            bounds.emplace(bound, value.value);
            thresholds.emplace(type, bounds);
        }
        else
        {
            threshold->second.emplace(bound, value.value);
        }
    }
    ThresholdIntf::value(thresholds, true);
}

void HealthMetric::checkThreshold(ThresholdIntf::Type type,
                                  ThresholdIntf::Bound bound, double value)
{
    auto threshold = std::make_tuple(type, bound);
    auto thresholds = ThresholdIntf::value();

    if (thresholds.contains(type) && thresholds[type].contains(bound))
    {
        auto thresholdValue = thresholds[type][bound];
        auto assertions = ThresholdIntf::asserted();
        if (value > thresholdValue)
        {
            if (!assertions.contains(threshold))
            {
                assertions.insert(threshold);
                ThresholdIntf::asserted(assertions);
                ThresholdIntf::assertionChanged(type, bound, true, value);
                auto tConfig = config.thresholds.at(threshold);
                if (tConfig.log)
                {
                    error(
                        "ASSERT: Health Metric {METRIC} crossed {TYPE} upper threshold",
                        "METRIC", config.name, "TYPE",
                        sdbusplus::message::convert_to_string(type));
                    startUnit(bus, tConfig.target);
                }
            }
            return;
        }
        else if (assertions.contains(threshold))
        {
            assertions.erase(threshold);
            ThresholdIntf::asserted(assertions);
            ThresholdIntf::assertionChanged(type, bound, false, value);
            if (config.thresholds.find(threshold)->second.log)
            {
                info(
                    "DEASSERT: Health Metric {METRIC} is below {TYPE} upper threshold",
                    "METRIC", config.name, "TYPE",
                    sdbusplus::message::convert_to_string(type));
            }
        }
    }
}

void HealthMetric::checkThresholds(double value)
{
    if (!ThresholdIntf::value().empty())
    {
        for (auto type :
             {ThresholdIntf::Type::HardShutdown,
              ThresholdIntf::Type::SoftShutdown,
              ThresholdIntf::Type::PerformanceLoss,
              ThresholdIntf::Type::Critical, ThresholdIntf::Type::Warning})
        {
            checkThreshold(type, ThresholdIntf::Bound::Upper, value);
        }
    }
}

void HealthMetric::update(MValue value)
{
    // Maintain window size for metric
    if (history.size() >= config.windowSize)
    {
        history.pop_front();
    }
    history.push_back(value.user);

    if (history.size() < config.windowSize)
    {
        // Wait for the metric to have enough samples to calculate average
        info("Not enough samples to calculate average");
        return;
    }

    double average = (std::accumulate(history.begin(), history.end(), 0.0)) /
                     history.size();
    ValueIntf::value(average);
    checkThresholds(value.monitor);
}

void HealthMetric::create(const paths_t& bmcPaths)
{
    info("Create Health Metric: {METRIC}", "METRIC", config.name);
    initProperties();

    std::vector<association_t> associations;
    static constexpr auto forwardAssociation = "measuring";
    static constexpr auto reverseAssociation = "measured_by";
    for (const auto& bmcPath : bmcPaths)
    {
        /*
         * This metric is "measuring" the health for the BMC at bmcPath
         * The BMC at bmcPath is "measured_by" this metric.
         */
        associations.push_back(
            {forwardAssociation, reverseAssociation, bmcPath});
    }
    AssociationIntf::associations(associations);
}

} // namespace phosphor::health::metric
