/*
 * SPDX-FileCopyrightText: Copyright (c) 2022-2024. All rights
 * reserved. SPDX-License-Identifier: Apache-2.0
 */
#include "config_provider.hpp"

#include <boost/container/flat_map.hpp>
#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/async/match.hpp>
#include <sdbusplus/bus/match.hpp>
#include <xyz/openbmc_project/ObjectMapper/client.hpp>

#include <ranges>
#include <string>

PHOSPHOR_LOG2_USING;

using VariantType =
    std::variant<std::vector<std::string>, std::string, int64_t, uint64_t,
                 double, int32_t, uint32_t, int16_t, uint16_t, uint8_t, bool>;
using ConfigMap = boost::container::flat_map<std::string, VariantType>;
using ConfigData = boost::container::flat_map<std::string, ConfigMap>;

namespace gpio_presence
{

ConfigProvider::ConfigProvider(sdbusplus::async::context& ctx,
                               const std::string& interface) :
    interface(interface), ctx(ctx)
{}

auto ConfigProvider::initialize(AddedCallback addConfig,
                                RemovedCallback removeConfig)
    -> sdbusplus::async::task<void>
{
    ctx.spawn(handleInterfacesAdded(addConfig));
    ctx.spawn(handleInterfacesRemoved(removeConfig));

    co_await getConfig(addConfig);
}

auto ConfigProvider::getConfig(AddedCallback addConfig)
    -> sdbusplus::async::task<void>
{
    auto client = sdbusplus::client::xyz::openbmc_project::ObjectMapper<>(ctx)
                      .service("xyz.openbmc_project.ObjectMapper")
                      .path("/xyz/openbmc_project/object_mapper");

    debug("calling 'GetSubTree' to find instances of {INTF}", "INTF",
          interface);

    using SubTreeType =
        std::map<std::string, std::map<std::string, std::vector<std::string>>>;
    SubTreeType res = {};

    try
    {
        std::vector<std::string> interfaces = {interface};
        res = co_await client.get_sub_tree("/xyz/openbmc_project/inventory", 0,
                                           interfaces);
    }
    catch (std::exception& e)
    {
        error("Failed GetSubTree call for configuration interface: {ERR}",
              "ERR", e);
    }

    if (res.empty())
    {
        co_return;
    }

    // call the user callback for all the device that is already available
    for (auto& [path, serviceInterfaceMap] : res)
    {
        for (const auto& service :
             std::ranges::views::keys(serviceInterfaceMap))
        {
            debug("found configuration interface at {SERVICE} {PATH} {INTF}",
                  "SERVICE", service, "PATH", path, "INTF", interface);

            addConfig(path);
        }
    }
}

namespace rules_intf = sdbusplus::bus::match::rules;

const auto senderRule = rules_intf::sender("xyz.openbmc_project.EntityManager");

auto ConfigProvider::handleInterfacesAdded(AddedCallback addConfig)
    -> sdbusplus::async::task<void>
{
    debug("setting up dbus match for interfaces added");

    sdbusplus::async::match addedMatch(
        ctx, rules_intf::interfacesAdded() + senderRule);

    while (!ctx.stop_requested())
    {
        auto tmp = co_await addedMatch
                       .next<sdbusplus::message::object_path, ConfigData>();

        auto [objPath, intfMap] = std::move(tmp);

        debug("Detected interface added on {OBJPATH}", "OBJPATH", objPath);

        if (!std::ranges::contains(std::views::keys(intfMap), interface))
        {
            continue;
        }

        try
        {
            addConfig(objPath);
        }
        catch (std::exception& e)
        {
            error("Incomplete or invalid config found: {ERR}", "ERR", e);
        }
    }
};

auto ConfigProvider::handleInterfacesRemoved(RemovedCallback removeConfig)
    -> sdbusplus::async::task<void>
{
    debug("setting up dbus match for interfaces removed");

    sdbusplus::async::match removedMatch(
        ctx, rules_intf::interfacesRemoved() + senderRule);

    while (!ctx.stop_requested())
    {
        auto tmp = co_await removedMatch.next<sdbusplus::message::object_path,
                                              std::vector<std::string>>();
        auto [objectPath, interfaces] = std::move(tmp);

        if (!std::ranges::contains(interfaces, interface))
        {
            continue;
        }

        debug("Detected interface {INTF} removed on {OBJPATH}", "INTF",
              interface, "OBJPATH", objectPath);

        removeConfig(objectPath);
    }
};

} // namespace gpio_presence
