#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", 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, std::numeric_limits<double>::quiet_NaN());
            thresholds.emplace(type, bounds);
        }
        else
        {
            threshold->second.emplace(bound, value.value);
        }
    }
    ThresholdIntf::value(thresholds, true);
}

bool didThresholdViolate(ThresholdIntf::Bound bound, double thresholdValue,
                         double value)
{
    switch (bound)
    {
        case ThresholdIntf::Bound::Lower:
        {
            return (value < thresholdValue);
        }
        case ThresholdIntf::Bound::Upper:
        {
            return (value > thresholdValue);
        }
        default:
        {
            error("Invalid threshold bound {BOUND}", "BOUND", bound);
            return false;
        }
    }
}

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

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

void HealthMetric::checkThresholds(MValue 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::Lower, value);
            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.current);

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

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

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
