#pragma once

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.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())
        {
            lg2::error(
                "Empty response from mapper GetSubTree, SubTree={SUBTREE}, Interface={INTERFACE}, Depth={DEPTH}",
                "SUBTREE", path, "INTERFACE", interface, "DEPTH", 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())
        {
            lg2::error(
                "Empty response from mapper GetSubTreePaths, SubTree={SUBTREE}, Interface={INTERFACE}, Depth={DEPTH}",
                "SUBTREE", path, "INTERFACE", interface, "DEPTH", 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()
                lg2::error("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
