#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);
}

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",
                  std::to_underlying(bound));
            return false;
        }
    }
}

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 (didThresholdViolate(bound, thresholdValue, value))
        {
            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::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.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
