#pragma once

#include <sdbusplus/bus.hpp>
#include <sdbusplus/message.hpp>
#include <phosphor-logging/log.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/elog-errors.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

namespace util
{
namespace detail
{
namespace errors = sdbusplus::xyz::openbmc_project::Common::Error;
} // namespace detail

/** @brief Alias for PropertiesChanged signal callbacks. */
template <typename ...T>
using Properties = std::map<std::string, sdbusplus::message::variant<T...>>;

namespace sdbusplus
{

/** @brief Get the bus connection. */
static auto& getBus() __attribute__((pure));
static auto& getBus()
{
    static auto bus = ::sdbusplus::bus::new_default();
    return bus;
}

/** @brief Invoke a method. */
template <typename ...Args>
static auto callMethod(
        ::sdbusplus::bus::bus& bus,
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& method,
        Args&& ... args)
{
    auto reqMsg = bus.new_method_call(
            busName.c_str(),
            path.c_str(),
            interface.c_str(),
            method.c_str());
    reqMsg.append(std::forward<Args>(args)...);
    auto respMsg = bus.call(reqMsg);

    if (respMsg.is_method_error())
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
                "Failed to invoke DBus method.",
                phosphor::logging::entry("PATH=%s", path.c_str()),
                phosphor::logging::entry(
                    "INTERFACE=%s", interface.c_str()),
                phosphor::logging::entry("METHOD=%s", method.c_str()));
        phosphor::logging::elog<detail::errors::InternalFailure>();
    }

    return respMsg;
}

/** @brief Invoke a method. */
template <typename ...Args>
static auto callMethod(
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& method,
        Args&& ... args)
{
    return callMethod(
            getBus(),
            busName,
            path,
            interface,
            method,
            std::forward<Args>(args)...);
}

/** @brief Invoke a method and read the response. */
template <typename Ret, typename ...Args>
static auto callMethodAndRead(
        ::sdbusplus::bus::bus& bus,
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& method,
        Args&& ... args)
{
    ::sdbusplus::message::message respMsg =
        callMethod<Args...>(
                bus,
                busName,
                path,
                interface,
                method,
                std::forward<Args>(args)...);
    Ret resp;
    respMsg.read(resp);
    return resp;
}

/** @brief Invoke a method and read the response. */
 template <typename Ret, typename ...Args>
static auto callMethodAndRead(
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& method,
        Args&& ... args)
{
    return callMethodAndRead<Ret>(
            getBus(),
            busName,
            path,
            interface,
            method,
            std::forward<Args>(args)...);
}


/** @brief Get service from the mapper. */
static auto getService(
        ::sdbusplus::bus::bus& bus,
        const std::string& path,
        const std::string& interface)
{
    using namespace std::literals::string_literals;
    using GetObject = std::map<std::string, std::vector<std::string>>;

    auto mapperResp = callMethodAndRead<GetObject>(
            bus,
            "xyz.openbmc_project.ObjectMapper"s,
            "/xyz/openbmc_project/object_mapper"s,
            "xyz.openbmc_project.ObjectMapper"s,
            "GetObject"s,
            path,
            GetObject::mapped_type{interface});

    if (mapperResp.empty())
    {
        phosphor::logging::log<phosphor::logging::level::INFO>(
                "Object not found.",
                phosphor::logging::entry("PATH=%s", path.c_str()),
                phosphor::logging::entry(
                    "INTERFACE=%s", interface.c_str()));
        phosphor::logging::elog<detail::errors::InternalFailure>();
    }
    return mapperResp.begin()->first;
}

/** @brief Get a property without mapper lookup. */
template <typename Property>
static auto getProperty(
        ::sdbusplus::bus::bus& bus,
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& property)
{
    using namespace std::literals::string_literals;

    auto msg = callMethod(
            bus,
            busName,
            path,
            "org.freedesktop.DBus.Properties"s,
            "Get"s,
            interface,
            property);
    ::sdbusplus::message::variant<Property> value;
    msg.read(value);
    return value.template get<Property>();
}

/** @brief Get a property without mapper lookup. */
template <typename Property>
static auto getProperty(
        const std::string& busName,
        const std::string& path,
        const std::string& interface,
        const std::string& property)
{
    return getProperty<Property>(
            getBus(),
            busName,
            path,
            interface,
            property);
}

/** @brief Get a property with mapper lookup. */
template <typename Property>
static auto getProperty(
        ::sdbusplus::bus::bus& bus,
        const std::string& path,
        const std::string& interface,
        const std::string& property)
{
    return getProperty<Property>(
            bus,
            getService(bus, path, interface),
            path,
            interface,
            property);
}

/** @brief Get a property with mapper lookup. */
template <typename Property>
static auto getProperty(
        const std::string& path,
        const std::string& interface,
        const std::string& property)
{
    return getProperty<Property>(
            getBus(),
            path,
            interface,
            property);
}

} // namespace sdbusplus
} // namespace util
