/**
 * 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 "init.hpp"

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

#include <fmt/format.h>

#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>

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

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

using json = nlohmann::json;
using namespace phosphor::logging;

void getProperties(Manager* mgr, const Group& group)
{
    for (const auto& member : group.getMembers())
    {
        try
        {
            // Check if property already cached
            auto value = mgr->getProperty(member, group.getInterface(),
                                          group.getProperty());
            if (value == std::nullopt)
            {
                // Property not in cache, attempt to add it
                mgr->addObjects(member, group.getInterface(),
                                group.getProperty());
            }
        }
        catch (const util::DBusMethodError& dme)
        {
            // Configured dbus object does not exist on dbus yet?
            // TODO How to handle this? Create timer to keep checking for
            // object/service to appear? When to stop checking?
        }
    }
}

void nameHasOwner(Manager* mgr, const Group& group)
{
    std::string lastName = "";
    for (const auto& member : group.getMembers())
    {
        std::string servName = "";
        auto intf = group.getInterface();
        try
        {
            servName = mgr->getService(member, intf);
            if (!servName.empty() && lastName != servName)
            {
                // Member not provided by same service as last group member
                lastName = servName;
                auto hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
                    mgr->getBus(), "org.freedesktop.DBus",
                    "/org/freedesktop/DBus", "org.freedesktop.DBus",
                    "NameHasOwner", servName);
                // Update service name owner state of group object
                mgr->setOwner(member, servName, intf, hasOwner);
            }
            if (servName.empty())
            {
                // Path and/or interface configured does not exist on dbus?
                // TODO How to handle this? Create timer to keep checking for
                // object/service to appear? When to stop checking?
                log<level::ERR>(
                    fmt::format(
                        "Unable to get service name for path {}, interface {}",
                        member, intf)
                        .c_str());
            }
        }
        catch (const util::DBusMethodError& dme)
        {
            if (!servName.empty())
            {
                // Failed to get service name owner state
                mgr->setOwner(member, servName, intf, false);
            }
            else
            {
                // Path and/or interface configured does not exist on dbus?
                // TODO How to handle this? Create timer to keep checking for
                // object/service to appear? When to stop checking?
                log<level::ERR>(
                    fmt::format(
                        "Unable to get service name for path {}, interface {}",
                        member, intf)
                        .c_str());
                throw dme;
            }
        }
    }
}

enableTrigger triggerInit(const json& jsonObj, const std::string& eventName,
                          std::vector<std::unique_ptr<ActionBase>>& actions)
{
    // Get the method handler if configured
    auto handler = methods.end();
    if (jsonObj.contains("method"))
    {
        auto method = jsonObj["method"].get<std::string>();
        std::transform(method.begin(), method.end(), method.begin(), tolower);
        handler = methods.find(method);
    }

    for (auto& action : actions)
    {
        // Groups are optional, so a method is only required if there are groups
        // i.e.) An init triggered event without any groups results in just
        // running the actions
        if (!action->getGroups().empty() && handler == methods.end())
        {
            // Construct list of available methods
            auto availMethods = std::accumulate(
                std::next(methods.begin()), methods.end(),
                methods.begin()->first, [](auto list, auto method) {
                    return std::move(list) + ", " + method.first;
                });
            auto msg =
                fmt::format("Event '{}' requires a supported method given to "
                            "be init driven, available methods: {}",
                            eventName, availMethods);
            log<level::ERR>(msg.c_str());
            throw std::runtime_error(msg.c_str());
        }
    }

    return [handler = std::move(handler)](
               const std::string& eventName, Manager* mgr,
               std::vector<std::unique_ptr<ActionBase>>& actions) {
        for (auto& action : actions)
        {
            for (const auto& group : action->getGroups())
            {
                // Call method handler for each group in the actions
                handler->second(mgr, group);
            }
            // Run the action
            action->run();
        }
    };
}

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