/**
 * 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);
    }

    return [handler = std::move(handler)](
               const std::string& eventName, Manager* mgr,
               const std::vector<Group>& groups,
               std::vector<std::unique_ptr<ActionBase>>& actions) {
        // Event groups are optional, so a method is only required if there
        // are event groups i.e.) An init triggered event without any event
        // groups results in just running the actions
        if (!groups.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());
        }

        for (const auto& group : groups)
        {
            // Call method handler for each group to populate cache
            handler->second(mgr, group);
        }
        for (auto& action : actions)
        {
            // Run each action after initializing all the groups
            action->run();
        }
    };
}

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