#include "numeric_threshold.hpp"

#include <phosphor-logging/log.hpp>

NumericThreshold::NumericThreshold(
    boost::asio::io_context& ioc, Sensors sensorsIn,
    std::vector<std::string> sensorNames,
    std::vector<std::unique_ptr<interfaces::TriggerAction>> actionsIn,
    Milliseconds dwellTimeIn, numeric::Direction direction,
    double thresholdValueIn) :
    ioc(ioc),
    sensors(std::move(sensorsIn)), actions(std::move(actionsIn)),
    dwellTime(dwellTimeIn), direction(direction),
    thresholdValue(thresholdValueIn)
{
    details.reserve(sensors.size());
    for (size_t i = 0; i < sensors.size(); i++)
    {
        details.emplace_back(sensorNames[i], thresholdValue, false, ioc);
    }
}

NumericThreshold::~NumericThreshold()
{}

void NumericThreshold::initialize()
{
    for (auto& sensor : sensors)
    {
        sensor->registerForUpdates(weak_from_this());
    }
}

NumericThreshold::ThresholdDetail&
    NumericThreshold::getDetails(interfaces::Sensor& sensor)
{
    auto it =
        std::find_if(sensors.begin(), sensors.end(),
                     [&sensor](const auto& x) { return &sensor == x.get(); });
    auto index = std::distance(sensors.begin(), it);
    return details.at(index);
}

void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
                                     Milliseconds timestamp)
{}

void NumericThreshold::sensorUpdated(interfaces::Sensor& sensor,
                                     Milliseconds timestamp, double value)
{
    auto& [sensorName, prevValue, dwell, timer] = getDetails(sensor);
    bool decreasing = thresholdValue < prevValue && thresholdValue > value;
    bool increasing = thresholdValue > prevValue && thresholdValue < value;

    if (dwell && (increasing || decreasing))
    {
        timer.cancel();
        dwell = false;
    }
    if ((direction == numeric::Direction::decreasing && decreasing) ||
        (direction == numeric::Direction::increasing && increasing) ||
        (direction == numeric::Direction::either && (increasing || decreasing)))
    {
        startTimer(sensorName, timestamp, value, dwell, timer);
    }

    prevValue = value;
}

void NumericThreshold::startTimer(const std::string& sensorName,
                                  Milliseconds timestamp, double value,
                                  bool& dwell, boost::asio::steady_timer& timer)
{
    if (dwellTime == Milliseconds::zero())
    {
        commit(sensorName, timestamp, value);
    }
    else
    {
        dwell = true;
        timer.expires_after(dwellTime);
        timer.async_wait([this, sensorName, timestamp, value,
                          &dwell](const boost::system::error_code ec) {
            if (ec)
            {
                phosphor::logging::log<phosphor::logging::level::DEBUG>(
                    "Timer has been canceled");
                return;
            }
            commit(sensorName, timestamp, value);
            dwell = false;
        });
    }
}

void NumericThreshold::commit(const std::string& sensorName,
                              Milliseconds timestamp, double value)
{
    for (const auto& action : actions)
    {
        action->commit(sensorName, timestamp, value);
    }
}
