#include "trigger.hpp"

#include "messages/collect_trigger_id.hpp"
#include "messages/trigger_presence_changed_ind.hpp"
#include "trigger_manager.hpp"
#include "types/report_types.hpp"
#include "types/trigger_types.hpp"
#include "utils/contains.hpp"
#include "utils/conversion_trigger.hpp"
#include "utils/transform.hpp"

#include <phosphor-logging/log.hpp>

Trigger::Trigger(
    boost::asio::io_context& ioc,
    const std::shared_ptr<sdbusplus::asio::object_server>& objServer,
    TriggerId&& idIn, const std::string& nameIn,
    const std::vector<TriggerAction>& triggerActionsIn,
    const std::shared_ptr<std::vector<std::string>> reportIdsIn,
    std::vector<std::shared_ptr<interfaces::Threshold>>&& thresholdsIn,
    interfaces::TriggerManager& triggerManager,
    interfaces::JsonStorage& triggerStorageIn,
    const interfaces::TriggerFactory& triggerFactory, Sensors sensorsIn) :
    id(std::move(idIn)),
    name(nameIn), triggerActions(std::move(triggerActionsIn)),
    path(triggerDir + *id), reportIds(std::move(reportIdsIn)),
    thresholds(std::move(thresholdsIn)),
    fileName(std::to_string(std::hash<std::string>{}(*id))),
    triggerStorage(triggerStorageIn), sensors(std::move(sensorsIn)),
    messanger(ioc)
{
    deleteIface = objServer->add_unique_interface(
        path, deleteIfaceName, [this, &ioc, &triggerManager](auto& dbusIface) {
            dbusIface.register_method("Delete", [this, &ioc, &triggerManager] {
                if (persistent)
                {
                    triggerStorage.remove(fileName);
                }
                messanger.send(messages::TriggerPresenceChangedInd{
                    messages::Presence::Removed, *id, {}});
                boost::asio::post(ioc, [this, &triggerManager] {
                    triggerManager.removeTrigger(this);
                });
            });
        });

    triggerIface = objServer->add_unique_interface(
        path, triggerIfaceName, [this, &triggerFactory](auto& dbusIface) {
            persistent = storeConfiguration();
            dbusIface.register_property_rw(
                "Persistent", persistent,
                sdbusplus::vtable::property_::emits_change,
                [this](bool newVal, const auto&) {
                    if (newVal == persistent)
                    {
                        return 1;
                    }
                    if (newVal)
                    {
                        persistent = storeConfiguration();
                    }
                    else
                    {
                        triggerStorage.remove(fileName);
                        persistent = false;
                    }
                    return 1;
                },
                [this](const auto&) { return persistent; });

            dbusIface.register_property_rw(
                "Thresholds", TriggerThresholdParams{},
                sdbusplus::vtable::property_::emits_change,
                [this, &triggerFactory](auto newVal, auto& oldVal) {
                    auto newThresholdParams = std::visit(
                        utils::ToLabeledThresholdParamConversion(), newVal);
                    triggerFactory.updateThresholds(
                        thresholds, *id, triggerActions, reportIds, sensors,
                        newThresholdParams);
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    return fromLabeledThresholdParam(getLabeledThresholds());
                });

            dbusIface.register_property_rw(
                "Sensors", SensorsInfo{},
                sdbusplus::vtable::property_::emits_change,
                [this, &triggerFactory](auto newVal, auto& oldVal) {
                    auto labeledSensorInfo =
                        triggerFactory.getLabeledSensorsInfo(newVal);
                    triggerFactory.updateSensors(sensors, labeledSensorInfo);
                    for (const auto& threshold : thresholds)
                    {
                        threshold->updateSensors(sensors);
                    }
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    return utils::fromLabeledSensorsInfo(
                        getLabeledSensorInfo());
                });

            dbusIface.register_property_rw(
                "ReportNames", *reportIds,
                sdbusplus::vtable::property_::emits_change,
                [this](auto newVal, auto& oldVal) {
                    TriggerManager::verifyReportIds(newVal);
                    *reportIds = newVal;
                    messanger.send(messages::TriggerPresenceChangedInd{
                        messages::Presence::Exist, *id, *reportIds});
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) { return *reportIds; });

            dbusIface.register_property_r(
                "Discrete", isDiscreate(), sdbusplus::vtable::property_::const_,
                [this](const auto& x) { return isDiscreate(); });

            dbusIface.register_property_rw(
                "Name", name, sdbusplus::vtable::property_::emits_change,
                [this](auto newVal, auto& oldVal) {
                    name = oldVal = newVal;
                    return 1;
                },
                [this](const auto&) { return name; });

            dbusIface.register_property_r(
                "TriggerActions", std::vector<std::string>(),
                sdbusplus::vtable::property_::const_, [this](const auto&) {
                    return utils::transform(triggerActions,
                                            [](const auto& action) {
                                                return actionToString(action);
                                            });
                });
        });

    for (const auto& threshold : thresholds)
    {
        threshold->initialize();
    }

    messanger.on_receive<messages::CollectTriggerIdReq>(
        [this](const auto& msg) {
            if (utils::contains(*reportIds, msg.reportId))
            {
                messanger.send(messages::CollectTriggerIdResp{*id});
            }
        });

    messanger.send(messages::TriggerPresenceChangedInd{
        messages::Presence::Exist, *id, *reportIds});
}

bool Trigger::storeConfiguration() const
{
    try
    {
        nlohmann::json data;

        auto labeledThresholdParams =
            std::visit(utils::ToLabeledThresholdParamConversion(),
                       fromLabeledThresholdParam(getLabeledThresholds()));

        data["Version"] = triggerVersion;
        data["Id"] = *id;
        data["Name"] = name;
        data["ThresholdParamsDiscriminator"] = labeledThresholdParams.index();
        data["TriggerActions"] =
            utils::transform(triggerActions, [](const auto& action) {
                return actionToString(action);
            });
        data["ThresholdParams"] =
            utils::labeledThresholdParamsToJson(labeledThresholdParams);
        data["ReportIds"] = *reportIds;
        data["Sensors"] = getLabeledSensorInfo();

        triggerStorage.store(fileName, data);
    }
    catch (const std::exception& e)
    {
        phosphor::logging::log<phosphor::logging::level::ERR>(
            "Failed to store a trigger in storage",
            phosphor::logging::entry("EXCEPTION_MSG=%s", e.what()));
        return false;
    }
    return true;
}

std::vector<LabeledSensorInfo> Trigger::getLabeledSensorInfo() const
{
    return utils::transform(sensors, [](const auto& sensor) {
        return sensor->getLabeledSensorInfo();
    });
}

std::vector<LabeledThresholdParam> Trigger::getLabeledThresholds() const
{
    return utils::transform(thresholds, [](const auto& threshold) {
        return threshold->getThresholdParam();
    });
}

bool Trigger::isDiscreate() const
{
    const auto labeledThresholds = getLabeledThresholds();

    return utils::isFirstElementOfType<std::monostate>(labeledThresholds) ||
           utils::isFirstElementOfType<discrete::LabeledThresholdParam>(
               labeledThresholds);
}
