#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/dbus_path_utils.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)),
    path(utils::pathAppend(utils::constants::triggerDirPath, *id)),
    name(nameIn), triggerActions(std::move(triggerActionsIn)),
    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);
                    TriggerManager::verifyThresholdParams(newThresholdParams);
                    triggerFactory.updateThresholds(
                        thresholds, *id, triggerActions, reportIds, sensors,
                        newThresholdParams);
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    return fromLabeledThresholdParam(getLabeledThresholds());
                });

            dbusIface.register_property_rw(
                "DiscreteThresholds", std::vector<discrete::ThresholdParam>{},
                sdbusplus::vtable::property_::emits_change,
                [this, &triggerFactory](
                    const std::vector<discrete::ThresholdParam>& newVal,
                    std::vector<discrete::ThresholdParam>& oldVal) {
                    LabeledTriggerThresholdParams newThresholdParams =
                        utils::ToLabeledThresholdParamConversion()(newVal);
                    TriggerManager::verifyThresholdParams(newThresholdParams);
                    triggerFactory.updateThresholds(
                        thresholds, *id, triggerActions, reportIds, sensors,
                        newThresholdParams);
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    TriggerThresholdParams unlabeled =
                        fromLabeledThresholdParam(getLabeledThresholds());
                    auto* ptr =
                        std::get_if<std::vector<discrete::ThresholdParam>>(
                            &unlabeled);
                    if (ptr == nullptr)
                    {
                        // If internal type doesn't match, return empty set
                        return std::vector<discrete::ThresholdParam>{};
                    }
                    return *ptr;
                });

            dbusIface.register_property_rw(
                "NumericThresholds", std::vector<numeric::ThresholdParam>{},
                sdbusplus::vtable::property_::emits_change,
                [this, &triggerFactory](
                    const std::vector<numeric::ThresholdParam>& newVal,
                    std::vector<numeric::ThresholdParam>& oldVal) {
                    LabeledTriggerThresholdParams newThresholdParams =
                        utils::ToLabeledThresholdParamConversion()(newVal);
                    TriggerManager::verifyThresholdParams(newThresholdParams);
                    triggerFactory.updateThresholds(
                        thresholds, *id, triggerActions, reportIds, sensors,
                        newThresholdParams);
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    TriggerThresholdParams unlabeled =
                        fromLabeledThresholdParam(getLabeledThresholds());
                    auto* ptr =
                        std::get_if<std::vector<numeric::ThresholdParam>>(
                            &unlabeled);
                    if (ptr == nullptr)
                    {
                        // If internal type doesn't match, return empty set
                        return std::vector<numeric::ThresholdParam>{};
                    }
                    return *ptr;
                });
            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(
                "Reports", std::vector<sdbusplus::message::object_path>(),
                sdbusplus::vtable::property_::emits_change,
                [this](auto newVal, auto& oldVal) {
                    auto newReportIds = utils::transform<std::vector>(
                        newVal, [](const auto& path) {
                            return utils::reportPathToId(path);
                        });
                    TriggerManager::verifyReportIds(newReportIds);
                    *reportIds = newReportIds;
                    messanger.send(messages::TriggerPresenceChangedInd{
                        messages::Presence::Exist, *id, *reportIds});
                    oldVal = std::move(newVal);
                    return 1;
                },
                [this](const auto&) {
                    return utils::transform<std::vector>(
                        *reportIds, [](const auto& id) {
                            return utils::pathAppend(
                                utils::constants::reportDirPath, id);
                        });
                });

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

            dbusIface.register_property_rw(
                "Name", name, sdbusplus::vtable::property_::emits_change,
                [this](auto newVal, auto& oldVal) {
                    if (newVal.length() > utils::constants::maxIdNameLength)
                    {
                        throw errors::InvalidArgument("Name",
                                                      "Name is too long.");
                    }
                    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::isDiscrete() const
{
    const auto labeledThresholds = getLabeledThresholds();
    if (labeledThresholds.empty())
    {
        return true;
    }

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