#pragma once

#include <sdbusplus/bus.hpp>
#include <sdbusplus/message.hpp>
#include <sdbusplus/bus/match.hpp>

struct Loop;

namespace phosphor
{
namespace dbus
{
namespace monitoring
{

/** @class SDBusPlus
 *  @brief DBus access delegate implementation for sdbusplus.
 */
class SDBusPlus
{
    private:
        static auto& getBus()
        {
            static auto bus = sdbusplus::bus::new_default();
            return bus;
        }

        static auto& getWatches()
        {
            static std::vector<sdbusplus::bus::match::match> watches;
            return watches;
        }

    public:
        /** @brief Invoke a method; ignore reply. */
        template <typename ...Args>
        static void callMethodNoReply(
            const std::string& busName,
            const std::string& path,
            const std::string& interface,
            const std::string& method,
            Args&& ... args)
        {
            auto reqMsg = getBus().new_method_call(
                              busName.c_str(),
                              path.c_str(),
                              interface.c_str(),
                              method.c_str());
            reqMsg.append(std::forward<Args>(args)...);
            getBus().call_noreply(reqMsg);

            // TODO: openbmc/openbmc#1719
            // invoke these methods async, with a callback
            // handler that checks for errors and logs.
        }

        /** @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)
        {
            auto reqMsg = getBus().new_method_call(
                              busName.c_str(),
                              path.c_str(),
                              interface.c_str(),
                              method.c_str());
            reqMsg.append(std::forward<Args>(args)...);
            return getBus().call(reqMsg);
        }

        /** @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)
        {
            Ret resp;
            sdbusplus::message::message respMsg =
                callMethod<Args...>(
                    busName,
                    path,
                    interface,
                    method,
                    std::forward<Args>(args)...);
            respMsg.read(resp);
            return resp;
        }

        /** @brief Register a DBus signal callback. */
        static auto addMatch(
            const std::string& match,
            const sdbusplus::bus::match::match::callback_t& callback)
        {
            getWatches().emplace_back(
                    getBus(),
                    match,
                    callback);
        }

        friend Loop;
};

} // namespace monitoring
} // namespace dbus
} // namespace phosphor
