#pragma once

#include "dbus_types.hpp"

#include <sdbusplus/bus/match.hpp>

namespace openpower::pels
{

namespace match_rules = sdbusplus::bus::match::rules;

/**
 * @class DBusWatcher
 *
 * The base class for the PropertyWatcher and InterfaceWatcher classes.
 */
class DBusWatcher
{
  public:
    DBusWatcher() = delete;
    virtual ~DBusWatcher() = default;
    DBusWatcher(const DBusWatcher&) = default;
    DBusWatcher& operator=(const DBusWatcher&) = default;
    DBusWatcher(DBusWatcher&&) = default;
    DBusWatcher& operator=(DBusWatcher&&) = default;

    /**
     * @brief Constructor
     *
     * @param[in] path - The D-Bus path that will be watched
     * @param[in] interface - The D-Bus interface that will be watched
     */
    DBusWatcher(const std::string& path, const std::string& interface) :
        _path(path), _interface(interface)
    {}

  protected:
    /**
     * @brief The D-Bus path
     */
    std::string _path;

    /**
     * @brief The D-Bus interface
     */
    std::string _interface;

    /**
     * @brief The match objects for the propertiesChanged and
     *        interfacesAdded signals.
     */
    std::vector<sdbusplus::bus::match_t> _matches;
};

/**
 * @class PropertyWatcher
 *
 * This class allows the user to be kept up to data with a D-Bus
 * property's value.  It does this by calling a user specified function
 * that is passed the variant that contains the property's value when:
 *
 * 1) The property is read when the class is constructed, if
 *    the property is on D-Bus at the time.
 * 2) The property changes (via a property changed signal).
 * 3) An interfacesAdded signal is received with that property.
 *
 * The DataInterface class is used to access D-Bus, and is a template
 * to avoid any circular include issues as that class is one of the
 * users of this one.
 */
template <typename DataIface>
class PropertyWatcher : public DBusWatcher
{
  public:
    PropertyWatcher() = delete;
    ~PropertyWatcher() = default;
    PropertyWatcher(const PropertyWatcher&) = delete;
    PropertyWatcher& operator=(const PropertyWatcher&) = delete;
    PropertyWatcher(PropertyWatcher&&) = delete;
    PropertyWatcher& operator=(PropertyWatcher&&) = delete;

    using PropertySetFunc = std::function<void(const DBusValue&)>;

    /**
     * @brief Constructor
     *
     * Reads the property if it is on D-Bus, and sets up the match
     * objects for the propertiesChanged and interfacesAdded signals.
     *
     * @param[in] bus - The sdbusplus bus object
     * @param[in] path - The D-Bus path of the property
     * @param[in] interface - The D-Bus interface that contains the property
     * @param[in] propertyName - The property name
     * @param[in] service - The D-Bus service to use for the property read.
     *                      Can be empty to look it up instead.
     * @param[in] dataIface - The DataInterface object
     * @param[in] func - The callback used any time the property is read
     */
    PropertyWatcher(sdbusplus::bus_t& bus, const std::string& path,
                    const std::string& interface,
                    const std::string& propertyName, const std::string& service,
                    const DataIface& dataIface, PropertySetFunc func) :
        DBusWatcher(path, interface),
        _name(propertyName), _setFunc(func)
    {
        _matches.emplace_back(
            bus, match_rules::propertiesChanged(_path, _interface),
            std::bind(std::mem_fn(&PropertyWatcher::propChanged), this,
                      std::placeholders::_1));

        _matches.emplace_back(
            bus,
            match_rules::interfacesAdded() + match_rules::argNpath(0, _path),
            std::bind(std::mem_fn(&PropertyWatcher::interfaceAdded), this,
                      std::placeholders::_1));

        try
        {
            read(dataIface, service);
        }
        catch (const sdbusplus::exception_t& e)
        {
            // Path doesn't exist now
        }
    }

    /**
     * @brief Constructor
     *
     * Reads the property if it is on D-Bus, and sets up the match
     * objects for the propertiesChanged and interfacesAdded signals.
     *
     * Unlike the other constructor, this contructor doesn't take the
     * service to use for the property read so it will look it up with
     * an ObjectMapper GetObject call.
     *
     * @param[in] bus - The sdbusplus bus object
     * @param[in] path - The D-Bus path of the property
     * @param[in] interface - The D-Bus interface that contains the property
     * @param[in] propertyName - The property name
     * @param[in] dataIface - The DataInterface object
     * @param[in] func - The callback used any time the property is read
     */
    PropertyWatcher(sdbusplus::bus_t& bus, const std::string& path,
                    const std::string& interface,
                    const std::string& propertyName, const DataIface& dataIface,
                    PropertySetFunc func) :
        PropertyWatcher(bus, path, interface, propertyName, "", dataIface, func)
    {}

    /**
     * @brief Reads the property on D-Bus, and calls
     *        the user defined function with the value.
     *
     * If the passed in service is empty, look up the service to use.
     *
     * @param[in] dataIface - The DataInterface object
     * @param[in] service - The D-Bus service to make the getProperty
     *                      call with, if not empty
     */
    void read(const DataIface& dataIface, std::string service)
    {
        if (service.empty())
        {
            service = dataIface.getService(_path, _interface);
        }

        if (!service.empty())
        {
            DBusValue value;
            dataIface.getProperty(service, _path, _interface, _name, value);

            _setFunc(value);
        }
    }

    /**
     * @brief The propertiesChanged callback
     *
     * Calls the user defined function with the property value
     *
     * @param[in] msg - The sdbusplus message object
     */
    void propChanged(sdbusplus::message_t& msg)
    {
        DBusInterface interface;
        DBusPropertyMap properties;

        msg.read(interface, properties);

        auto prop = properties.find(_name);
        if (prop != properties.end())
        {
            _setFunc(prop->second);
        }
    }

    /**
     * @brief The interfacesAdded callback
     *
     * Calls the user defined function with the property value
     *
     * @param[in] msg - The sdbusplus message object
     */
    void interfaceAdded(sdbusplus::message_t& msg)
    {
        sdbusplus::message::object_path path;
        DBusInterfaceMap interfaces;

        msg.read(path, interfaces);

        auto iface = interfaces.find(_interface);
        if (iface != interfaces.end())
        {
            auto prop = iface->second.find(_name);
            if (prop != iface->second.end())
            {
                _setFunc(prop->second);
            }
        }
    }

  private:
    /**
     * @brief The D-Bus property name
     */
    std::string _name;

    /**
     * @brief The function that will be called any time the
     *        property is read.
     */
    PropertySetFunc _setFunc;
};

/**
 * @class InterfaceWatcher
 *
 * This class allows the user to be kept up to data with a D-Bus
 * interface's properties..  It does this by calling a user specified
 * function that is passed a map of the D-Bus property names and values
 * on that interface when:
 *
 * 1) The interface is read when the class is constructed, if
 *    the interface is on D-Bus at the time.
 * 2) The interface has a property that changes (via a property changed signal).
 * 3) An interfacesAdded signal is received.
 *
 * The DataInterface class is used to access D-Bus, and is a template
 * to avoid any circular include issues as that class is one of the
 * users of this one.
 */
template <typename DataIface>
class InterfaceWatcher : public DBusWatcher
{
  public:
    InterfaceWatcher() = delete;
    ~InterfaceWatcher() = default;
    InterfaceWatcher(const InterfaceWatcher&) = delete;
    InterfaceWatcher& operator=(const InterfaceWatcher&) = delete;
    InterfaceWatcher(InterfaceWatcher&&) = delete;
    InterfaceWatcher& operator=(InterfaceWatcher&&) = delete;

    using InterfaceSetFunc = std::function<void(const DBusPropertyMap&)>;

    /**
     * @brief Constructor
     *
     * Reads all properties on the interface if it is on D-Bus,
     * and sets up the match objects for the propertiesChanged
     * and interfacesAdded signals.
     *
     * @param[in] bus - The sdbusplus bus object
     * @param[in] path - The D-Bus path of the property
     * @param[in] interface - The D-Bus interface that contains the property
     * @param[in] dataIface - The DataInterface object
     * @param[in] func - The callback used any time the property is read
     */
    InterfaceWatcher(sdbusplus::bus_t& bus, const std::string& path,
                     const std::string& interface, const DataIface& dataIface,
                     InterfaceSetFunc func) :
        DBusWatcher(path, interface),
        _setFunc(func)
    {
        _matches.emplace_back(
            bus, match_rules::propertiesChanged(_path, _interface),
            std::bind(std::mem_fn(&InterfaceWatcher::propChanged), this,
                      std::placeholders::_1));

        _matches.emplace_back(
            bus,
            match_rules::interfacesAdded() + match_rules::argNpath(0, _path),
            std::bind(std::mem_fn(&InterfaceWatcher::interfaceAdded), this,
                      std::placeholders::_1));

        try
        {
            read(dataIface);
        }
        catch (const sdbusplus::exception_t& e)
        {
            // Path doesn't exist now
        }
    }

    /**
     * @brief Reads the interface's properties on D-Bus, and
     * calls the the user defined function with the property map.
     *
     * @param[in] dataIface - The DataInterface object
     */
    void read(const DataIface& dataIface)
    {
        auto service = dataIface.getService(_path, _interface);
        if (!service.empty())
        {
            auto properties = dataIface.getAllProperties(service, _path,
                                                         _interface);

            _setFunc(properties);
        }
    }

    /**
     * @brief The propertiesChanged callback
     *
     * Calls the user defined function with the property map.  Only the
     * properties that changed will be in the map.
     *
     * @param[in] msg - The sdbusplus message object
     */
    void propChanged(sdbusplus::message_t& msg)
    {
        DBusInterface interface;
        DBusPropertyMap properties;

        msg.read(interface, properties);

        _setFunc(properties);
    }

    /**
     * @brief The interfacesAdded callback
     *
     * Calls the user defined function with the property map
     *
     * @param[in] msg - The sdbusplus message object
     */
    void interfaceAdded(sdbusplus::message_t& msg)
    {
        sdbusplus::message::object_path path;
        DBusInterfaceMap interfaces;

        msg.read(path, interfaces);

        auto iface = interfaces.find(_interface);
        if (iface != interfaces.end())
        {
            _setFunc(iface->second);
        }
    }

  private:
    /**
     * @brief The function that will be called any time the
     *        interface is read.
     */
    InterfaceSetFunc _setFunc;
};

} // namespace openpower::pels
