#pragma once

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

#include <format>

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

/**
 * @class DBusError
 *
 * The base class for the exceptions thrown on fails in the various
 * SDBusPlus calls.  Used so that a single catch statement can catch
 * any type of these exceptions.
 *
 * None of these exceptions will log anything when they are created,
 * it is up to the handler to do that if desired.
 */
class DBusError : public std::runtime_error
{
  public:
    explicit DBusError(const std::string& msg) : std::runtime_error(msg) {}
};

/**
 * @class DBusMethodError
 *
 * Thrown on a DBus Method call failure
 */
class DBusMethodError : public DBusError
{
  public:
    DBusMethodError(const std::string& busName, const std::string& path,
                    const std::string& interface, const std::string& method) :
        DBusError(std::format("DBus method failed: {} {} {} {}", busName, path,
                              interface, method)),
        busName(busName), path(path), interface(interface), method(method)
    {}

    const std::string busName;
    const std::string path;
    const std::string interface;
    const std::string method;
};

/**
 * @class DBusServiceError
 *
 * Thrown when a service lookup fails.  Usually this points to
 * the object path not being present in D-Bus.
 */
class DBusServiceError : public DBusError
{
  public:
    DBusServiceError(const std::string& path, const std::string& interface) :
        DBusError(
            std::format("DBus service lookup failed: {} {}", path, interface)),
        path(path), interface(interface)
    {}

    const std::string path;
    const std::string interface;
};

/**
 * @class DBusPropertyError
 *
 * Thrown when a set/get property fails.
 */
class DBusPropertyError : public DBusError
{
  public:
    DBusPropertyError(const std::string& msg, const std::string& busName,
                      const std::string& path, const std::string& interface,
                      const std::string& property) :
        DBusError(msg + std::format(": {} {} {} {}", busName, path, interface,
                                    property)),
        busName(busName), path(path), interface(interface), property(property)
    {}

    const std::string busName;
    const std::string path;
    const std::string interface;
    const std::string property;
};

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

/** @class SDBusPlus
 *  @brief DBus access delegate implementation for sdbusplus.
 */
class SDBusPlus
{
  public:
    /** @brief Get the bus connection. */
    static auto& getBus() __attribute__((pure))
    {
        static auto bus = sdbusplus::bus::new_default();
        return bus;
    }

    /** @brief Invoke a method. */
    template <typename... Args>
    static auto callMethod(sdbusplus::bus_t& 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)...);
        try
        {
            auto respMsg = bus.call(reqMsg);
            if (respMsg.is_method_error())
            {
                throw DBusMethodError{busName, path, interface, method};
            }
            return respMsg;
        }
        catch (const sdbusplus::exception_t&)
        {
            throw DBusMethodError{busName, path, interface, method};
        }
    }

    /** @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_t& bus, const std::string& busName,
                          const std::string& path, const std::string& interface,
                          const std::string& method, Args&&... args)
    {
        sdbusplus::message_t 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 subtree from the mapper without checking response. */
    static auto getSubTreeRaw(sdbusplus::bus_t& bus, const std::string& path,
                              const std::string& interface, int32_t depth)
    {
        using namespace std::literals::string_literals;

        using Path = std::string;
        using Intf = std::string;
        using Serv = std::string;
        using Intfs = std::vector<Intf>;
        using Objects = std::map<Path, std::map<Serv, Intfs>>;
        Intfs intfs = {interface};

        return callMethodAndRead<Objects>(
            bus, "xyz.openbmc_project.ObjectMapper"s,
            "/xyz/openbmc_project/object_mapper"s,
            "xyz.openbmc_project.ObjectMapper"s, "GetSubTree"s, path, depth,
            intfs);
    }

    /** @brief Get subtree from the mapper without checking response,
     * (multiple interfaces version). */
    static auto getSubTreeRaw(sdbusplus::bus_t& bus, const std::string& path,
                              const std::vector<std::string>& intfs,
                              int32_t depth)
    {
        using namespace std::literals::string_literals;

        using Path = std::string;
        using Intf = std::string;
        using Serv = std::string;
        using Intfs = std::vector<Intf>;
        using Objects = std::map<Path, std::map<Serv, Intfs>>;

        return callMethodAndRead<Objects>(
            bus, "xyz.openbmc_project.ObjectMapper"s,
            "/xyz/openbmc_project/object_mapper"s,
            "xyz.openbmc_project.ObjectMapper"s, "GetSubTree"s, path, depth,
            intfs);
    }

    /** @brief Get subtree from the mapper. */
    static auto getSubTree(sdbusplus::bus_t& bus, const std::string& path,
                           const std::string& interface, int32_t depth)
    {
        auto mapperResp = getSubTreeRaw(bus, path, interface, depth);
        if (mapperResp.empty())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Empty response from mapper GetSubTree",
                phosphor::logging::entry("SUBTREE=%s", path.c_str()),
                phosphor::logging::entry("INTERFACE=%s", interface.c_str()),
                phosphor::logging::entry("DEPTH=%u", depth));
            phosphor::logging::elog<detail::errors::InternalFailure>();
        }
        return mapperResp;
    }

    /** @brief Get subtree paths from the mapper without checking response. */
    static auto getSubTreePathsRaw(sdbusplus::bus_t& bus,
                                   const std::string& path,
                                   const std::string& interface, int32_t depth)
    {
        using namespace std::literals::string_literals;

        using Path = std::string;
        using Intf = std::string;
        using Intfs = std::vector<Intf>;
        using ObjectPaths = std::vector<Path>;
        Intfs intfs = {interface};

        return callMethodAndRead<ObjectPaths>(
            bus, "xyz.openbmc_project.ObjectMapper"s,
            "/xyz/openbmc_project/object_mapper"s,
            "xyz.openbmc_project.ObjectMapper"s, "GetSubTreePaths"s, path,
            depth, intfs);
    }

    /** @brief Get subtree paths from the mapper. */
    static auto getSubTreePaths(sdbusplus::bus_t& bus, const std::string& path,
                                const std::string& interface, int32_t depth)
    {
        auto mapperResp = getSubTreePathsRaw(bus, path, interface, depth);
        if (mapperResp.empty())
        {
            phosphor::logging::log<phosphor::logging::level::ERR>(
                "Empty response from mapper GetSubTreePaths",
                phosphor::logging::entry("SUBTREE=%s", path.c_str()),
                phosphor::logging::entry("INTERFACE=%s", interface.c_str()),
                phosphor::logging::entry("DEPTH=%u", depth));
            phosphor::logging::elog<detail::errors::InternalFailure>();
        }
        return mapperResp;
    }

    /** @brief Get service from the mapper without checking response. */
    static auto getServiceRaw(sdbusplus::bus_t& 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>>;

        return 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});
    }

    /** @brief Get service from the mapper. */
    static auto getService(sdbusplus::bus_t& bus, const std::string& path,
                           const std::string& interface)
    {
        try
        {
            auto mapperResp = getServiceRaw(bus, path, interface);

            if (mapperResp.empty())
            {
                // Should never happen.  A missing object would fail
                // in callMethodAndRead()
                phosphor::logging::log<phosphor::logging::level::ERR>(
                    "Empty mapper response on service lookup");
                throw DBusServiceError{path, interface};
            }
            return mapperResp.begin()->first;
        }
        catch (const DBusMethodError& e)
        {
            throw DBusServiceError{path, interface};
        }
    }

    /** @brief Get service from the mapper. */
    static auto getService(const std::string& path,
                           const std::string& interface)
    {
        return getService(getBus(), path, interface);
    }

    /** @brief Get managed objects. */
    template <typename Variant>
    static auto getManagedObjects(sdbusplus::bus_t& bus,
                                  const std::string& service,
                                  const std::string& path)
    {
        using namespace std::literals::string_literals;

        using Path = sdbusplus::message::object_path;
        using Intf = std::string;
        using Prop = std::string;
        using GetManagedObjects =
            std::map<Path, std::map<Intf, std::map<Prop, Variant>>>;

        return callMethodAndRead<GetManagedObjects>(
            bus, service, path, "org.freedesktop.DBus.ObjectManager"s,
            "GetManagedObjects"s);
    }

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

        auto service = getService(bus, path, interface);
        auto msg =
            callMethod(bus, service, path, "org.freedesktop.DBus.Properties"s,
                       "Get"s, interface, property);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus get property failed", service, path,
                                    interface, property};
        }
        std::variant<Property> value;
        msg.read(value);
        return std::get<Property>(value);
    }

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

    /** @brief Get a property variant with mapper lookup. */
    template <typename Variant>
    static auto getPropertyVariant(
        sdbusplus::bus_t& bus, const std::string& path,
        const std::string& interface, const std::string& property)
    {
        using namespace std::literals::string_literals;

        auto service = getService(bus, path, interface);
        auto msg =
            callMethod(bus, service, path, "org.freedesktop.DBus.Properties"s,
                       "Get"s, interface, property);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus get property variant failed", service,
                                    path, interface, property};
        }
        Variant value;
        msg.read(value);
        return value;
    }

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

    /** @brief Invoke a method and return without checking for error. */
    template <typename... Args>
    static auto callMethodAndReturn(
        sdbusplus::bus_t& 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);

        return respMsg;
    }

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

        auto msg = callMethodAndReturn(bus, service, path,
                                       "org.freedesktop.DBus.Properties"s,
                                       "Get"s, interface, property);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus get property failed", service, path,
                                    interface, property};
        }
        std::variant<Property> value;
        msg.read(value);
        return std::get<Property>(value);
    }

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

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

        auto msg = callMethodAndReturn(bus, service, path,
                                       "org.freedesktop.DBus.Properties"s,
                                       "Get"s, interface, property);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus get property variant failed", service,
                                    path, interface, property};
        }
        Variant value;
        msg.read(value);
        return value;
    }

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

    /** @brief Set a property with mapper lookup. */
    template <typename Property>
    static void setProperty(sdbusplus::bus_t& bus, const std::string& path,
                            const std::string& interface,
                            const std::string& property, Property&& value)
    {
        using namespace std::literals::string_literals;

        std::variant<Property> varValue(std::forward<Property>(value));

        auto service = getService(bus, path, interface);
        auto msg = callMethodAndReturn(bus, service, path,
                                       "org.freedesktop.DBus.Properties"s,
                                       "Set"s, interface, property, varValue);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus set property failed", service, path,
                                    interface, property};
        }
    }

    /** @brief Set a property with mapper lookup. */
    template <typename Property>
    static void setProperty(const std::string& path,
                            const std::string& interface,
                            const std::string& property, Property&& value)
    {
        return setProperty(getBus(), path, interface, property,
                           std::forward<Property>(value));
    }

    /** @brief Set a property without mapper lookup. */
    template <typename Property>
    static void setProperty(sdbusplus::bus_t& bus, const std::string& service,
                            const std::string& path,
                            const std::string& interface,
                            const std::string& property, Property&& value)
    {
        using namespace std::literals::string_literals;

        std::variant<Property> varValue(std::forward<Property>(value));

        auto msg = callMethodAndReturn(bus, service, path,
                                       "org.freedesktop.DBus.Properties"s,
                                       "Set"s, interface, property, varValue);
        if (msg.is_method_error())
        {
            throw DBusPropertyError{"DBus set property failed", service, path,
                                    interface, property};
        }
    }

    /** @brief Set a property without mapper lookup. */
    template <typename Property>
    static void setProperty(const std::string& service, const std::string& path,
                            const std::string& interface,
                            const std::string& property, Property&& value)
    {
        return setProperty(getBus(), service, path, interface, property,
                           std::forward<Property>(value));
    }

    /** @brief Invoke method with mapper lookup. */
    template <typename... Args>
    static auto lookupAndCallMethod(
        sdbusplus::bus_t& bus, const std::string& path,
        const std::string& interface, const std::string& method, Args&&... args)
    {
        return callMethod(bus, getService(bus, path, interface), path,
                          interface, method, std::forward<Args>(args)...);
    }

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

    /** @brief Invoke method and read with mapper lookup. */
    template <typename Ret, typename... Args>
    static auto lookupCallMethodAndRead(
        sdbusplus::bus_t& bus, const std::string& path,
        const std::string& interface, const std::string& method, Args&&... args)
    {
        return callMethodAndRead(bus, getService(bus, path, interface), path,
                                 interface, method,
                                 std::forward<Args>(args)...);
    }

    /** @brief Invoke method and read with mapper lookup. */
    template <typename Ret, typename... Args>
    static auto lookupCallMethodAndRead(
        const std::string& path, const std::string& interface,
        const std::string& method, Args&&... args)
    {
        return lookupCallMethodAndRead<Ret>(getBus(), path, interface, method,
                                            std::forward<Args>(args)...);
    }
};

} // namespace util
} // namespace fan
} // namespace phosphor
