/**
 * Copyright © 2021 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include "signal.hpp"

#include "../manager.hpp"
#include "action.hpp"
#include "group.hpp"
#include "handlers.hpp"
#include "trigger_aliases.hpp"

#include <nlohmann/json.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/bus/match.hpp>

#include <algorithm>
#include <functional>
#include <iterator>
#include <memory>
#include <numeric>
#include <utility>
#include <vector>

namespace phosphor::fan::control::json::trigger::signal
{

using json = nlohmann::json;
using namespace sdbusplus::bus::match;

void subscribe(const std::string& match, SignalPkg&& signalPkg,
               std::function<bool(SignalPkg&)> isSameSig, Manager* mgr)
{
    auto& signalData = mgr->getSignal(match);
    if (signalData.empty())
    {
        // Signal subscription doesnt exist, add signal package and subscribe
        std::unique_ptr<std::vector<SignalPkg>> pkgs =
            std::make_unique<std::vector<SignalPkg>>();
        pkgs->emplace_back(std::move(signalPkg));
        std::unique_ptr<sdbusplus::bus::match_t> ptrMatch = nullptr;
        if (!match.empty())
        {
            // Subscribe to signal
            ptrMatch = std::make_unique<sdbusplus::bus::match_t>(
                mgr->getBus(), match.c_str(),
                std::bind(std::mem_fn(&Manager::handleSignal), &(*mgr),
                          std::placeholders::_1, pkgs.get()));
        }
        signalData.emplace_back(std::move(pkgs), std::move(ptrMatch));
    }
    else
    {
        // Signal subscription already exists
        // Only a single signal data entry tied to each match is supported
        auto& pkgs = std::get<std::unique_ptr<std::vector<SignalPkg>>>(
            signalData.front());
        auto sameSignal = false;
        for (auto& pkg : *pkgs)
        {
            if (isSameSig(pkg))
            {
                // Same SignalObject signal to trigger event actions,
                // add actions to be run when signal for SignalObject received
                auto& pkgActions = std::get<TriggerActions>(signalPkg);
                auto& actions = std::get<TriggerActions>(pkg);
                actions.insert(actions.end(), pkgActions.begin(),
                               pkgActions.end());
                sameSignal = true;
                break;
            }
        }
        if (!sameSignal)
        {
            // Expected signal differs, add signal package
            pkgs->emplace_back(std::move(signalPkg));
        }
    }
}

void propertiesChanged(Manager* mgr, const Group& group,
                       TriggerActions& actions, const json&)
{
    // Groups are optional, but a signal triggered event with no groups
    // will do nothing since signals require a group
    for (const auto& member : group.getMembers())
    {
        // Setup property changed signal handler on the group member's
        // property
        const auto match =
            rules::propertiesChanged(member, group.getInterface());
        SignalPkg signalPkg = {
            Handlers::propertiesChanged,
            SignalObject(std::cref(member), std::cref(group.getInterface()),
                         std::cref(group.getProperty())),
            actions};
        auto isSameSig = [&prop = group.getProperty()](SignalPkg& pkg) {
            auto& obj = std::get<SignalObject>(pkg);
            return prop == std::get<Prop>(obj);
        };

        subscribe(match, std::move(signalPkg), isSameSig, mgr);
    }
}

void interfacesAdded(Manager* mgr, const Group& group, TriggerActions& actions,
                     const json&)
{
    // Groups are optional, but a signal triggered event with no groups
    // will do nothing since signals require a group
    for (const auto& member : group.getMembers())
    {
        // Setup interfaces added signal handler on the group member
        const auto match =
            rules::interfacesAdded() + rules::argNpath(0, member);
        SignalPkg signalPkg = {
            Handlers::interfacesAdded,
            SignalObject(std::cref(member), std::cref(group.getInterface()),
                         std::cref(group.getProperty())),
            actions};
        auto isSameSig = [&intf = group.getInterface()](SignalPkg& pkg) {
            auto& obj = std::get<SignalObject>(pkg);
            return intf == std::get<Intf>(obj);
        };

        subscribe(match, std::move(signalPkg), isSameSig, mgr);
    }
}

void interfacesRemoved(Manager* mgr, const Group& group,
                       TriggerActions& actions, const json&)
{
    // Groups are optional, but a signal triggered event with no groups
    // will do nothing since signals require a group
    for (const auto& member : group.getMembers())
    {
        // Setup interfaces removed signal handler on the group member
        const auto match =
            rules::interfacesRemoved() + rules::argNpath(0, member);
        SignalPkg signalPkg = {
            Handlers::interfacesRemoved,
            SignalObject(std::cref(member), std::cref(group.getInterface()),
                         std::cref(group.getProperty())),
            actions};
        auto isSameSig = [&intf = group.getInterface()](SignalPkg& pkg) {
            auto& obj = std::get<SignalObject>(pkg);
            return intf == std::get<Intf>(obj);
        };

        subscribe(match, std::move(signalPkg), isSameSig, mgr);
    }
}

void nameOwnerChanged(Manager* mgr, const Group& group, TriggerActions& actions,
                      const json&)
{
    std::vector<std::string> grpServices;
    // Groups are optional, but a signal triggered event with no groups
    // will do nothing since signals require a group
    for (const auto& member : group.getMembers())
    {
        auto serv = group.getService();
        if (serv.empty())
        {
            serv = Manager::getService(member, group.getInterface());
        }
        if (!serv.empty())
        {
            // No need to re-subscribe to the same service's nameOwnerChanged
            // signal when a prior group member provided by the same service
            // already did the subscription
            if (std::find(grpServices.begin(), grpServices.end(), serv) ==
                grpServices.end())
            {
                // Setup name owner changed signal handler on the group
                // member's service
                const auto match = rules::nameOwnerChanged(serv);
                SignalPkg signalPkg = {Handlers::nameOwnerChanged,
                                       SignalObject(), actions};
                // If signal match already exists, then the service will be the
                // same so add action to be run
                auto isSameSig = [](SignalPkg&) { return true; };

                subscribe(match, std::move(signalPkg), isSameSig, mgr);
                grpServices.emplace_back(serv);
            }
        }
        else
        {
            // Unable to construct nameOwnerChanged match string
            // Path and/or interface configured does not exist on dbus yet?
            // TODO How to handle this? Create timer to keep checking for
            // service to appear? When to stop checking?
            lg2::error(
                "Events will not be triggered by name owner changed"
                "signals from service of path {MEMBER}, interface {GROUP_INTERFACE}",
                "MEMBER", member, "GROUP_INTERFACE", group.getInterface());
        }
    }
}

void member(Manager* mgr, const Group& group, TriggerActions& actions,
            const json&)
{
    // No SignalObject required to associate to this signal
    SignalPkg signalPkg = {Handlers::member, SignalObject(), actions};
    // If signal match already exists, then the member signal will be the
    // same so add action to be run
    auto isSameSig = [](SignalPkg&) { return true; };

    // Groups are optional, but a signal triggered event with no groups
    // will do nothing since signals require a group
    for (const auto& member : group.getMembers())
    {
        // Subscribe for signal from each group member
        const auto match =
            rules::type::signal() + rules::member(group.getProperty()) +
            rules::path(member) + rules::interface(group.getInterface());

        subscribe(match, std::move(signalPkg), isSameSig, mgr);
    }
}

enableTrigger triggerSignal(
    const json& jsonObj, const std::string& eventName,
    std::vector<std::unique_ptr<ActionBase>>& /*actions*/)
{
    auto subscriber = signals.end();
    if (jsonObj.contains("signal"))
    {
        auto signal = jsonObj["signal"].get<std::string>();
        std::transform(signal.begin(), signal.end(), signal.begin(), tolower);
        subscriber = signals.find(signal);
    }
    if (subscriber == signals.end())
    {
        // Construct list of available signals
        auto availSignals =
            std::accumulate(std::next(signals.begin()), signals.end(),
                            signals.begin()->first, [](auto list, auto signal) {
                                return std::move(list) + ", " + signal.first;
                            });
        lg2::error(
            "Event '{EVENT_NAME}' requires a supported signal given to be "
            "triggered by signal, available signals: {AVAILABLE_SIGNALS}",
            "EVENT_NAME", eventName, "AVAILABLE_SIGNALS", availSignals);
        throw std::runtime_error(
            "Event requires a supported signal given to be triggered by signal.");
    }

    return [subscriber = std::move(subscriber),
            jsonObj](const std::string& /*eventName*/, Manager* mgr,
                     const std::vector<Group>& groups,
                     std::vector<std::unique_ptr<ActionBase>>& actions) {
        TriggerActions signalActions;
        std::for_each(actions.begin(), actions.end(),
                      [&signalActions](auto& action) {
                          signalActions.emplace_back(std::ref(action));
                      });
        for (const auto& group : groups)
        {
            // Call signal subscriber for each group
            subscriber->second(mgr, group, signalActions, jsonObj);
        }
    };
}

} // namespace phosphor::fan::control::json::trigger::signal
