#include "trigger_factory.hpp"

#include "discrete_threshold.hpp"
#include "numeric_threshold.hpp"
#include "on_change_threshold.hpp"
#include "sensor.hpp"
#include "trigger.hpp"
#include "trigger_actions.hpp"
#include "utils/clock.hpp"
#include "utils/dbus_mapper.hpp"
#include "utils/transform.hpp"

namespace ts = utils::tstring;

TriggerFactory::TriggerFactory(
    std::shared_ptr<sdbusplus::asio::connection> bus,
    std::shared_ptr<sdbusplus::asio::object_server> objServer,
    SensorCache& sensorCache) :
    bus(std::move(bus)),
    objServer(std::move(objServer)), sensorCache(sensorCache)
{}

void TriggerFactory::updateDiscreteThresholds(
    std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors,
    const std::vector<discrete::LabeledThresholdParam>& newParams) const
{
    auto oldThresholds = currentThresholds;
    std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;

    bool isCurrentOnChange = false;
    if (oldThresholds.size() == 1 &&
        std::holds_alternative<std::monostate>(
            oldThresholds.back()->getThresholdParam()))
    {
        isCurrentOnChange = true;
    }

    newThresholds.reserve(newParams.size());

    if (!isCurrentOnChange)
    {
        for (const auto& labeledThresholdParam : newParams)
        {
            auto paramChecker = [labeledThresholdParam](auto threshold) {
                return labeledThresholdParam ==
                       std::get<discrete::LabeledThresholdParam>(
                           threshold->getThresholdParam());
            };
            if (auto existing = std::find_if(oldThresholds.begin(),
                                             oldThresholds.end(), paramChecker);
                existing != oldThresholds.end())
            {
                newThresholds.emplace_back(*existing);
                oldThresholds.erase(existing);
                continue;
            }

            makeDiscreteThreshold(newThresholds, triggerId, triggerActions,
                                  reportIds, sensors, labeledThresholdParam);
        }
    }
    else
    {
        for (const auto& labeledThresholdParam : newParams)
        {
            makeDiscreteThreshold(newThresholds, triggerId, triggerActions,
                                  reportIds, sensors, labeledThresholdParam);
        }
    }
    if (newParams.empty())
    {
        if (isCurrentOnChange)
        {
            newThresholds.emplace_back(*oldThresholds.begin());
        }
        else
        {
            makeOnChangeThreshold(newThresholds, triggerId, triggerActions,
                                  reportIds, sensors);
        }
    }
    currentThresholds = std::move(newThresholds);
}

void TriggerFactory::updateNumericThresholds(
    std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors,
    const std::vector<numeric::LabeledThresholdParam>& newParams) const
{
    auto oldThresholds = currentThresholds;
    std::vector<std::shared_ptr<interfaces::Threshold>> newThresholds;

    newThresholds.reserve(newParams.size());

    for (const auto& labeledThresholdParam : newParams)
    {
        auto paramChecker = [labeledThresholdParam](auto threshold) {
            return labeledThresholdParam ==
                   std::get<numeric::LabeledThresholdParam>(
                       threshold->getThresholdParam());
        };
        if (auto existing = std::find_if(oldThresholds.begin(),
                                         oldThresholds.end(), paramChecker);
            existing != oldThresholds.end())
        {
            newThresholds.emplace_back(*existing);
            oldThresholds.erase(existing);
            continue;
        }

        makeNumericThreshold(newThresholds, triggerId, triggerActions,
                             reportIds, sensors, labeledThresholdParam);
    }
    currentThresholds = std::move(newThresholds);
}

void TriggerFactory::updateThresholds(
    std::vector<std::shared_ptr<interfaces::Threshold>>& currentThresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors,
    const LabeledTriggerThresholdParams& newParams) const
{
    if (isTriggerThresholdDiscrete(newParams))
    {
        const auto& labeledDiscreteThresholdParams =
            std::get<std::vector<discrete::LabeledThresholdParam>>(newParams);

        updateDiscreteThresholds(currentThresholds, triggerId, triggerActions,
                                 reportIds, sensors,
                                 labeledDiscreteThresholdParams);
    }
    else
    {
        const auto& labeledNumericThresholdParams =
            std::get<std::vector<numeric::LabeledThresholdParam>>(newParams);

        updateNumericThresholds(currentThresholds, triggerId, triggerActions,
                                reportIds, sensors,
                                labeledNumericThresholdParams);
    }
}

void TriggerFactory::makeDiscreteThreshold(
    std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors,
    const discrete::LabeledThresholdParam& thresholdParam) const
{
    std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;

    const std::string& thresholdName = thresholdParam.at_label<ts::UserId>();
    discrete::Severity severity = thresholdParam.at_label<ts::Severity>();
    auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
    const std::string& thresholdValue =
        thresholdParam.at_label<ts::ThresholdValue>();

    action::discrete::fillActions(actions, triggerActions, severity,
                                  bus->get_io_context(), reportIds);

    thresholds.emplace_back(std::make_shared<DiscreteThreshold>(
        bus->get_io_context(), triggerId, sensors, std::move(actions),
        Milliseconds(dwellTime), thresholdValue, thresholdName, severity,
        std::make_unique<Clock>()));
}

void TriggerFactory::makeNumericThreshold(
    std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors,
    const numeric::LabeledThresholdParam& thresholdParam) const
{
    std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;

    auto type = thresholdParam.at_label<ts::Type>();
    auto dwellTime = Milliseconds(thresholdParam.at_label<ts::DwellTime>());
    auto direction = thresholdParam.at_label<ts::Direction>();
    auto thresholdValue = double{thresholdParam.at_label<ts::ThresholdValue>()};

    action::numeric::fillActions(actions, triggerActions, type, thresholdValue,
                                 bus->get_io_context(), reportIds);

    thresholds.emplace_back(std::make_shared<NumericThreshold>(
        bus->get_io_context(), triggerId, sensors, std::move(actions),
        dwellTime, direction, thresholdValue, type, std::make_unique<Clock>()));
}

void TriggerFactory::makeOnChangeThreshold(
    std::vector<std::shared_ptr<interfaces::Threshold>>& thresholds,
    const std::string& triggerId,
    const std::vector<TriggerAction>& triggerActions,
    const std::shared_ptr<std::vector<std::string>>& reportIds,
    const Sensors& sensors) const
{
    std::vector<std::unique_ptr<interfaces::TriggerAction>> actions;

    action::discrete::onChange::fillActions(actions, triggerActions,
                                            bus->get_io_context(), reportIds);

    thresholds.emplace_back(std::make_shared<OnChangeThreshold>(
        triggerId, sensors, std::move(actions), std::make_unique<Clock>()));
}

std::unique_ptr<interfaces::Trigger> TriggerFactory::make(
    const std::string& idIn, const std::string& name,
    const std::vector<std::string>& triggerActionsIn,
    const std::vector<std::string>& reportIdsIn,
    interfaces::TriggerManager& triggerManager,
    interfaces::JsonStorage& triggerStorage,
    const LabeledTriggerThresholdParams& labeledThresholdParams,
    const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
{
    const auto& sensors = getSensors(labeledSensorsInfo);
    auto triggerActions = utils::transform(triggerActionsIn,
                                           [](const auto& triggerActionStr) {
        return toTriggerAction(triggerActionStr);
    });
    std::vector<std::shared_ptr<interfaces::Threshold>> thresholds;
    auto id = std::make_unique<const std::string>(idIn);

    auto reportIds = std::make_shared<std::vector<std::string>>(reportIdsIn);

    updateThresholds(thresholds, *id, triggerActions, reportIds, sensors,
                     labeledThresholdParams);

    return std::make_unique<Trigger>(
        bus->get_io_context(), objServer, std::move(id), name, triggerActions,
        reportIds, std::move(thresholds), triggerManager, triggerStorage, *this,
        sensors);
}

Sensors TriggerFactory::getSensors(
    const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
{
    Sensors sensors;
    updateSensors(sensors, labeledSensorsInfo);
    return sensors;
}

void TriggerFactory::updateSensors(
    Sensors& currentSensors,
    const std::vector<LabeledSensorInfo>& labeledSensorsInfo) const
{
    Sensors oldSensors = currentSensors;
    Sensors newSensors;

    for (const auto& labeledSensorInfo : labeledSensorsInfo)
    {
        auto existing = std::find_if(oldSensors.begin(), oldSensors.end(),
                                     [labeledSensorInfo](auto sensor) {
            return labeledSensorInfo == sensor->getLabeledSensorInfo();
        });

        if (existing != oldSensors.end())
        {
            newSensors.emplace_back(*existing);
            oldSensors.erase(existing);
            continue;
        }

        const auto& service = labeledSensorInfo.at_label<ts::Service>();
        const auto& sensorPath = labeledSensorInfo.at_label<ts::Path>();
        const auto& metadata = labeledSensorInfo.at_label<ts::Metadata>();

        newSensors.emplace_back(sensorCache.makeSensor<Sensor>(
            service, sensorPath, metadata, bus->get_io_context(), bus));
    }

    currentSensors = std::move(newSensors);
}

std::vector<LabeledSensorInfo>
    TriggerFactory::getLabeledSensorsInfo(boost::asio::yield_context& yield,
                                          const SensorsInfo& sensorsInfo) const
{
    if (sensorsInfo.empty())
    {
        return {};
    }
    auto tree = utils::getSubTreeSensors(yield, bus);
    return parseSensorTree(tree, sensorsInfo);
}

std::vector<LabeledSensorInfo>
    TriggerFactory::getLabeledSensorsInfo(const SensorsInfo& sensorsInfo) const
{
    if (sensorsInfo.empty())
    {
        return {};
    }
    auto tree = utils::getSubTreeSensors(bus);
    return parseSensorTree(tree, sensorsInfo);
}

std::vector<LabeledSensorInfo>
    TriggerFactory::parseSensorTree(const std::vector<utils::SensorTree>& tree,
                                    const SensorsInfo& sensorsInfo)
{
    return utils::transform(sensorsInfo, [&tree](const auto& item) {
        const auto& [sensorPath, metadata] = item;
        auto found = std::find_if(
            tree.begin(), tree.end(),
            [path = sensorPath](const auto& x) { return x.first == path; });

        if (tree.end() != found)
        {
            const auto& [service, ifaces] = found->second.front();
            return LabeledSensorInfo(service, sensorPath, metadata);
        }
        throw std::runtime_error("Not found");
    });
}
