#include <Thresholds.hpp>
#include <VariantVisitors.hpp>
#include <boost/algorithm/string/replace.hpp>
#include <boost/lexical_cast.hpp>
#include <fstream>
#include <iostream>

static constexpr bool DEBUG = false;
constexpr size_t MAX_THRESHOLDS = 4;

namespace thresholds
{
unsigned int toBusValue(const Level &level)
{
    switch (level)
    {
        case (Level::WARNING):
        {
            return 0;
        }
        case (Level::CRITICAL):
        {
            return 1;
        }
        default:
        {
            return -1;
        }
    }
}

std::string toBusValue(const Direction &direction)
{
    switch (direction)
    {
        case (Direction::LOW):
        {
            return "less than";
        }
        case (Direction::HIGH):
        {
            return "greater than";
        }
        default:
        {
            return "err";
        }
    }
}

bool ParseThresholdsFromConfig(
    const SensorData &sensorData,
    std::vector<thresholds::Threshold> &thresholdVector,
    const std::string *matchLabel)
{
    for (const auto &item : sensorData)
    {
        if (item.first.find("Thresholds") == std::string::npos)
        {
            continue;
        }
        if (matchLabel != nullptr)
        {
            auto labelFind = item.second.find("Label");
            if (labelFind == item.second.end())
                continue;
            if (mapbox::util::apply_visitor(VariantToStringVisitor(),
                                            labelFind->second) != *matchLabel)
                continue;
        }
        auto directionFind = item.second.find("Direction");
        auto severityFind = item.second.find("Severity");
        auto valueFind = item.second.find("Value");
        if (valueFind == item.second.end() ||
            severityFind == item.second.end() ||
            directionFind == item.second.end())
        {
            std::cerr << "Malformed threshold in configuration\n";
            return false;
        }
        Level level;
        Direction direction;
        if (mapbox::util::apply_visitor(VariantToUnsignedIntVisitor(),
                                        severityFind->second) == 0)
        {
            level = Level::WARNING;
        }
        else
        {
            level = Level::CRITICAL;
        }
        if (mapbox::util::apply_visitor(VariantToStringVisitor(),
                                        directionFind->second) == "less than")
        {
            direction = Direction::LOW;
        }
        else
        {
            direction = Direction::HIGH;
        }
        float val = mapbox::util::apply_visitor(VariantToFloatVisitor(),
                                                valueFind->second);

        thresholdVector.emplace_back(level, direction, val);
    }
    return true;
}

void persistThreshold(const std::string &path, const std::string &baseInterface,
                      const thresholds::Threshold &threshold,
                      std::shared_ptr<sdbusplus::asio::connection> &conn)
{
    for (int ii = 0; ii < MAX_THRESHOLDS; ii++)
    {
        std::string thresholdInterface =
            baseInterface + ".Thresholds" + std::to_string(ii);
        conn->async_method_call(
            [&, path, threshold, thresholdInterface](
                const boost::system::error_code &ec,
                const boost::container::flat_map<std::string, BasicVariantType>
                    &result) {
                if (ec)
                {
                    return; // threshold not supported
                }

                auto directionFind = result.find("Direction");
                auto severityFind = result.find("Severity");
                auto valueFind = result.find("Value");
                if (valueFind == result.end() || severityFind == result.end() ||
                    directionFind == result.end())
                {
                    std::cerr << "Malformed threshold in configuration\n";
                    return;
                }
                unsigned int level = mapbox::util::apply_visitor(
                    VariantToUnsignedIntVisitor(), severityFind->second);

                std::string dir = mapbox::util::apply_visitor(
                    VariantToStringVisitor(), directionFind->second);
                if ((toBusValue(threshold.level) != level) ||
                    (toBusValue(threshold.direction) != dir))
                {
                    return; // not the droid we're looking for
                }

                sdbusplus::message::variant<double> value(threshold.value);
                conn->async_method_call(
                    [](const boost::system::error_code &ec) {
                        if (ec)
                        {
                            std::cerr << "Error setting threshold " << ec
                                      << "\n";
                        }
                    },
                    ENTITY_MANAGER_NAME, path,
                    "org.freedesktop.DBus.Properties", "Set",
                    thresholdInterface, "Value", value);
            },
            ENTITY_MANAGER_NAME, path, "org.freedesktop.DBus.Properties",
            "GetAll", thresholdInterface);
    }
}

static constexpr std::array<const char *, 4> ATTR_TYPES = {"lcrit", "min",
                                                           "max", "crit"};

bool ParseThresholdsFromAttr(
    std::vector<thresholds::Threshold> &threshold_vector,
    const std::string &input_path, const double scale_factor)
{
    for (auto &type : ATTR_TYPES)
    {
        auto attr_path = boost::replace_all_copy(input_path, "input", type);
        std::ifstream attr_file(attr_path);
        if (!attr_file.good())
            continue;
        std::string attr;
        std::getline(attr_file, attr);
        attr_file.close();

        Level level;
        Direction direction;
        double val = std::stod(attr) / scale_factor;
        if (type == "min" || type == "max")
            level = Level::WARNING;
        else
            level = Level::CRITICAL;
        if (type == "min" || type == "lcrit")
            direction = Direction::LOW;
        else
            direction = Direction::HIGH;

        if (DEBUG)
            std::cout << "Threshold: " << attr_path << ": " << val << "\n";

        threshold_vector.emplace_back(level, direction, val);
    }
    // no thresholds is allowed, not an error so return true always
    return true;
}

bool HasCriticalInterface(
    const std::vector<thresholds::Threshold> &threshold_vector)
{
    for (auto &threshold : threshold_vector)
    {
        if (threshold.level == Level::CRITICAL)
            return true;
    }
    return false;
}

bool HasWarningInterface(
    const std::vector<thresholds::Threshold> &threshold_vector)
{
    for (auto &threshold : threshold_vector)
    {
        if (threshold.level == Level::WARNING)
            return true;
    }
    return false;
}
} // namespace thresholds
