#pragma once

#include "dbus_utility.hpp"
#include "logging.hpp"
#include "managed_store.hpp"

#include <sdbusplus/message/native_types.hpp>
#include <sdbusplus/unpack_properties.hpp>

#include <set>

#ifdef UNIT_TEST_BUILD
#include "test/g3/mock_managed_store.hpp" // NOLINT
#endif

namespace redfish
{
namespace dbus_utils
{

struct UnpackErrorPrinter
{
    void operator()(const sdbusplus::UnpackErrorReason reason,
                    const std::string& property) const noexcept
    {
        BMCWEB_LOG_ERROR
            << "DBUS property error in property: " << property << ", reason: "
            << static_cast<
                   std::underlying_type_t<sdbusplus::UnpackErrorReason>>(
                   reason);
    }
};

inline void getPropertiesFromManagedObjects(
    const dbus::utility::ManagedObjectType& managedObjects,
    const std::string& objPath, const std::string& interface,
    dbus::utility::DBusPropertiesMap& properties)
{
    for (const auto& object : managedObjects)
    {
        if (object.first.str != objPath)
        {
            continue;
        }

        for (const auto& interfaceMap : object.second)
        {
            if (interfaceMap.first != interface)
            {
                continue;
            }
            properties = interfaceMap.second;
        }
    }
}

// Populates |serviceNames| list with unique services found in the given
// subtree.
inline std::vector<std::string> getServiceNamesFromSubtree(
    const dbus::utility::MapperGetSubTreeResponse& subtree)
{
    std::set<std::string> uniqueServiceNames;
    for (const auto& [_, serviceMap] : subtree)
    {
        for (const auto& servicePair : serviceMap)
        {
            uniqueServiceNames.insert(servicePair.first);
        }
    }
    return {uniqueServiceNames.begin(), uniqueServiceNames.end()};
}

// Checks if any one of given interfaces is present in the service map.
inline bool findInterfacesInServiceMap(
    const dbus::utility::MapperServiceMap& serviceMap,
    std::span<const std::string_view> interfaces)
{
    for (const auto& [serviceName, interfaceList] : serviceMap)
    {
        if (std::find_first_of(interfaceList.begin(), interfaceList.end(),
                               interfaces.begin(),
                               interfaces.end()) != interfaceList.end())
        {
            return true;
        }
    }
    return false;
}

/**
 * Recursively gets managed objects under given object path from each service in
 * the given list of service names and maps objects to the service name they
 * originate from.
 *
 * @param[in] serviceList               Mutable list of unique service names.
 * @param[in] objPath                   Managed objects are requested relative
 *                                      to this path.
 * @param[in,out] managedObjectsByService   Service name to managed objects map.
 * @param[in] callback                  Callback to execute after getting
 *                                      managed objects from all service names
 *                                      in the list.
 */
template <typename Callback>
inline void getManagedObjectsInEachServiceCallback(
    std::vector<std::string>&& serviceList,
    const sdbusplus::message::object_path& objPath,
    std::unordered_map<std::string, dbus::utility::ManagedObjectType>&&
        managedObjectsByService,
    const managedStore::ManagedObjectStoreContext& context, Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "GetManagedObjects from next service in list.";
    if (serviceList.empty())
    {
        BMCWEB_LOG_DEBUG << "Recieved managed objects from all services.";
        callback(managedObjectsByService);
        return;
    }
    std::string serviceName = serviceList.back();
    serviceList.pop_back();

    managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
        serviceName, objPath, context,
        [serviceList{std::move(serviceList)}, serviceName, objPath,
         managedObjectsByService{std::move(managedObjectsByService)},
         context = context, callback{std::forward<Callback>(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& managedObjects) mutable {
        if (!ec)
        {
            managedObjectsByService[serviceName] = managedObjects;
        }
        getManagedObjectsInEachServiceCallback(
            std::move(serviceList), objPath, std::move(managedObjectsByService),
            context, std::forward<decltype(callback)>(callback));
        });
}

/**
 * Gets managed objects under given object path from each service in the given
 * list of service names.
 *
 * @param[in] serviceList               Mutable list of unique service names.
 * @param[in] objPath                   Managed objects are requested relative
 *                                      to this path.
 * @param[in] callback                  Callback to execute after getting
 *                                      managed objects from all service names
 *                                      in the list.
 */
template <typename Callback>
inline void getManagedObjectsInEachService(
    std::vector<std::string>&& serviceList,
    const sdbusplus::message::object_path& objPath,
    const managedStore::ManagedObjectStoreContext& context, Callback&& callback)
{
    BMCWEB_LOG_DEBUG << "Requesting managed objects from given list of "
                     << "services ";
    std::unordered_map<std::string, dbus::utility::ManagedObjectType>
        managedObjectsByService;
    if (serviceList.empty())
    {
        BMCWEB_LOG_ERROR << "Service list is empty";
        callback(managedObjectsByService);
        return;
    }
    std::string serviceName = serviceList.back();
    serviceList.pop_back();

    managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
        serviceName, objPath, context,
        [serviceList{std::move(serviceList)}, serviceName, objPath,
         managedObjectsByService{std::move(managedObjectsByService)},
         context = context, callback{std::forward<Callback>(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::ManagedObjectType& managedObjects) mutable {
        if (!ec)
        {
            managedObjectsByService[serviceName] = managedObjects;
        }
        getManagedObjectsInEachServiceCallback(
            std::move(serviceList), objPath, std::move(managedObjectsByService),
            context, std::forward<decltype(callback)>(callback));
        });
}

template <typename PropertyType>
void getProperty(const std::string& service, const std::string& path,
                 const std::string& interface, const std::string& property,
                 const managedStore::ManagedObjectStoreContext& requestContext,
                 std::function<void(const boost::system::error_code&,
                                    const PropertyType&)>&& callback)
{
    managedStore::KeyType keyType(managedStore::ManagedType::kManagedProperty,
                                  service, {path}, interface, property);
    BMCWEB_LOG_STATEFUL_DEBUG << "getProperty: Key " << keyType.toString()
                              << " requestContext "
                              << requestContext.toString();

    managedStore::GetManagedObjectStore()->getProperty(
        keyType, requestContext,
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DbusVariantType& managedProperty,
            [[maybe_unused]] uint64_t age_ms) {
        if (ec)
        {
            callback(ec, {});
            return;
        }
        const PropertyType* propertyValue =
            std::get_if<PropertyType>(&managedProperty);
        if (propertyValue)
        {
            callback(ec, *propertyValue);
            return;
        }
        callback(boost::system::errc::make_error_code(
                     boost::system::errc::invalid_argument),
                 {});
    });
}

template <typename PropertyType>
void getProperty(const std::string& service, const std::string& path,
                 const std::string& interface, const std::string& property,
                 const managedStore::ManagedObjectStoreContext& requestContext,
                 std::function<void(const boost::system::error_code&,
                                    const PropertyType&, uint64_t)>&& callback)
{
    managedStore::KeyType keyType(managedStore::ManagedType::kManagedProperty,
                                  service, {path}, interface, property);
    BMCWEB_LOG_STATEFUL_DEBUG << "getProperty: Key " << keyType.toString()
                              << " requestContext "
                              << requestContext.toString();

    managedStore::GetManagedObjectStore()->getProperty(
        keyType, requestContext,
        [callback{std::move(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::DbusVariantType& managedProperty,
            uint64_t age_ms) {
        if (ec)
        {
            callback(ec, {}, 0);
            return;
        }
        const PropertyType* propertyValue =
            std::get_if<PropertyType>(&managedProperty);
        if (propertyValue)
        {
            callback(ec, *propertyValue, age_ms);
            return;
        }
        callback(boost::system::errc::make_error_code(
                     boost::system::errc::invalid_argument),
                 {}, 0);
    });
}

inline void getAssociationEndPoints(
    const std::string& path,
    const managedStore::ManagedObjectStoreContext& requestContext,
    std::function<void(const boost::system::error_code&,
                       const dbus::utility::MapperEndPoints&)>&& callback)
{
    getProperty<dbus::utility::MapperEndPoints>(
        "xyz.openbmc_project.ObjectMapper", {path},
        "xyz.openbmc_project.Association", "endpoints", requestContext,
        std::move(callback));
}

template <typename Callback>
inline void
    checkDbusPathExists(const std::string& path,
                        const managedStore::ManagedObjectStoreContext& context,
                        Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getDbusObject(
        path, {}, context,
        [callback{std::forward<Callback>(callback)}](
            const boost::system::error_code& ec,
            const dbus::utility::MapperGetObject& objectNames) {
        callback(!ec && !objectNames.empty());
    });
}

template <typename Callback>
inline void getAssociatedSubTree(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getAssociatedSubTree(
        associatedPath, path, depth, interfaces, context,
        std::forward<Callback>(callback));
}

template <typename Callback>
inline void getAssociatedSubTreePaths(
    const sdbusplus::message::object_path& associatedPath,
    const sdbusplus::message::object_path& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getAssociatedSubTreePaths(
        associatedPath, path, depth, interfaces, context,
        std::forward<Callback>(callback));
}

template <typename Callback>
inline void getSubTree(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getSubTree(
        path, depth, interfaces, context,
        std::forward<Callback>(callback));
}

// Overload to support span of strings for interface names.
template <typename Callback>
inline void getSubTree(
    const std::string& path, int32_t depth, std::span<std::string> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getSubTree(
        path, depth, interfaces, context,
        std::forward<Callback>(callback));
}

template <typename Callback>
inline void getSubTreePaths(
    const std::string& path, int32_t depth,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getSubTreePaths(
        path, depth, interfaces, context,
        std::forward<Callback>(callback));
}

template <typename Callback>
inline void getManagedObjects(
    const std::string& service, const sdbusplus::message::object_path& path,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getManagedObjectsWithContext(
        service, path, context,
        std::forward<Callback>(callback));
}

template <typename Callback>
inline void getDbusObject(const std::string& path,
    std::span<const std::string_view> interfaces,
    const managedStore::ManagedObjectStoreContext& context,
    Callback&& callback)
{
    managedStore::GetManagedObjectStore()->getDbusObject(
        path, interfaces, context, std::forward<Callback>(callback));
}

} // namespace dbus_utils
} // namespace redfish
