#pragma once

#include "sdbusplus.hpp"
#include "types.hpp"
#include "zone.hpp"

#include <phosphor-logging/log.hpp>

namespace phosphor
{
namespace fan
{
namespace control
{
class Zone;

using namespace phosphor::fan;
using namespace sdbusplus::bus::match;
using namespace phosphor::logging;

/**
 * @brief Create a zone handler function object
 *
 * @param[in] handler - The handler being created
 *
 * @return - The created zone handler function object
 */
template <typename T>
auto make_zoneHandler(T&& handler)
{
    return ZoneHandler(std::forward<T>(handler));
}

/**
 * @brief Create a trigger function object
 *
 * @param[in] trigger - The trigger being created
 *
 * @return - The created trigger function object
 */
template <typename T>
auto make_trigger(T&& trigger)
{
    return Trigger(std::forward<T>(trigger));
}

/**
 * @brief Create a handler function object
 *
 * @param[in] handler - The handler being created
 *
 * @return - The created handler function object
 */
template <typename T, typename U>
auto make_handler(U&& handler)
{
    return T(std::forward<U>(handler));
}

/**
 * @brief Create an action function object
 *
 * @param[in] action - The action being created
 *
 * @return - The created action function object
 */
template <typename T>
auto make_action(T&& action)
{
    return Action(std::forward<T>(action));
}

/**
 * @struct Properties
 * @brief A set of match filter functors for Dbus property values. Each
 * functor provides an associated process for retrieving the value
 * for a given property and providing it to the given handler function.
 *
 * @tparam T - The type of the property value
 * @tparam U - The type of the handler
 */
template <typename T, typename U>
struct Properties
{
    Properties() = delete;
    ~Properties() = default;
    Properties(const Properties&) = default;
    Properties& operator=(const Properties&) = default;
    Properties(Properties&&) = default;
    Properties& operator=(Properties&&) = default;
    explicit Properties(U&& handler) :
        _path(""), _intf(""), _prop(""), _handler(std::forward<U>(handler))
    {}
    Properties(const char* path, const char* intf, const char* prop,
               U&& handler) :
        _path(path),
        _intf(intf), _prop(prop), _handler(std::forward<U>(handler))
    {}

    /** @brief Run signal handler function
     *
     * Extract the property from the PropertiesChanged
     * message and run the handler function.
     */
    void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg,
                    Zone& zone) const
    {
        if (msg)
        {
            std::string intf;
            msg.read(intf);
            if (intf != _intf)
            {
                // Interface name does not match on object
                return;
            }

            std::map<std::string, PropertyVariantType> props;
            msg.read(props);
            auto it = props.find(_prop);
            if (it == props.cend())
            {
                // Property not included in dictionary of properties changed
                return;
            }

            // Retrieve the property's value applying any visitors necessary
            auto value = zone.getPropertyValueVisitor<T>(_intf, _prop,
                                                         it->second);

            _handler(zone, _path, _intf, _prop, std::forward<T>(value));
        }
        else
        {
            try
            {
                auto val = zone.getPropertyByName<T>(_path, _intf, _prop);
                _handler(zone, _path, _intf, _prop, std::forward<T>(val));
            }
            catch (const sdbusplus::exception_t&)
            {
                // Property will not be used unless a property changed
                // signal message is received for this property.
            }
            catch (const util::DBusError&)
            {
                // Property will not be used unless a property changed
                // signal message is received for this property.
            }
        }
    }

    /** @brief Run init handler function
     *
     * Get the property from each member object of the group
     * and run the handler function.
     */
    void operator()(Zone& zone, const Group& group) const
    {
        std::for_each(
            group.begin(), group.end(),
            [&zone, handler = std::move(_handler)](const auto& member) {
            auto path = std::get<pathPos>(member);
            auto intf = std::get<intfPos>(member);
            auto prop = std::get<propPos>(member);
            try
            {
                auto val = zone.getPropertyByName<T>(path, intf, prop);
                handler(zone, path, intf, prop, std::forward<T>(val));
            }
            catch (const sdbusplus::exception_t&)
            {
                // Property value not sent to handler
            }
            catch (const util::DBusError&)
            {
                // Property value not sent to handler
            }
            });
    }

  private:
    const char* _path;
    const char* _intf;
    const char* _prop;
    U _handler;
};

/**
 * @brief Used to process a Dbus properties changed signal event
 *
 * @param[in] path - Object path
 * @param[in] intf - Object interface
 * @param[in] prop - Object property
 * @param[in] handler - Handler function to perform
 *
 * @tparam T - The type of the property
 * @tparam U - The type of the handler
 */
template <typename T, typename U>
auto propertiesChanged(const char* path, const char* intf, const char* prop,
                       U&& handler)
{
    return Properties<T, U>(path, intf, prop, std::forward<U>(handler));
}

/**
 * @brief Used to get the properties of an event's group
 *
 * @param[in] handler - Handler function to perform
 *
 * @tparam T - The type of all the properties
 * @tparam U - The type of the handler
 */
template <typename T, typename U>
auto getProperties(U&& handler)
{
    return Properties<T, U>(std::forward<U>(handler));
}

/**
 * @struct Interfaces Added
 * @brief A match filter functor for Dbus interfaces added signals
 *
 * @tparam T - The type of the property value
 * @tparam U - The type of the handler
 */
template <typename T, typename U>
struct InterfacesAdded
{
    InterfacesAdded() = delete;
    ~InterfacesAdded() = default;
    InterfacesAdded(const InterfacesAdded&) = default;
    InterfacesAdded& operator=(const InterfacesAdded&) = default;
    InterfacesAdded(InterfacesAdded&&) = default;
    InterfacesAdded& operator=(InterfacesAdded&&) = default;
    InterfacesAdded(const char* path, const char* intf, const char* prop,
                    U&& handler) :
        _path(path),
        _intf(intf), _prop(prop), _handler(std::forward<U>(handler))
    {}

    /** @brief Run signal handler function
     *
     * Extract the property from the InterfacesAdded
     * message and run the handler function.
     */
    void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg,
                    Zone& zone) const
    {
        if (msg)
        {
            sdbusplus::message::object_path op;

            msg.read(op);
            if (static_cast<const std::string&>(op) != _path)
            {
                // Object path does not match this handler's path
                return;
            }

            std::map<std::string, std::map<std::string, PropertyVariantType>>
                intfProp;
            msg.read(intfProp);
            auto itIntf = intfProp.find(_intf);
            if (itIntf == intfProp.cend())
            {
                // Interface not found on this handler's path
                return;
            }
            auto itProp = itIntf->second.find(_prop);
            if (itProp == itIntf->second.cend())
            {
                // Property not found on this handler's path
                return;
            }

            // Retrieve the property's value applying any visitors necessary
            auto value = zone.getPropertyValueVisitor<T>(_intf, _prop,
                                                         itProp->second);

            _handler(zone, _path, _intf, _prop, std::forward<T>(value));
        }
    }

  private:
    const char* _path;
    const char* _intf;
    const char* _prop;
    U _handler;
};

/**
 * @brief Used to process a Dbus interfaces added signal event
 *
 * @param[in] path - Object path
 * @param[in] intf - Object interface
 * @param[in] prop - Object property
 * @param[in] handler - Handler function to perform
 *
 * @tparam T - The type of the property
 * @tparam U - The type of the handler
 */
template <typename T, typename U>
auto interfacesAdded(const char* path, const char* intf, const char* prop,
                     U&& handler)
{
    return InterfacesAdded<T, U>(path, intf, prop, std::forward<U>(handler));
}

/**
 * @struct Interfaces Removed
 * @brief A match filter functor for Dbus interfaces removed signals
 *
 * @tparam U - The type of the handler
 */
template <typename U>
struct InterfacesRemoved
{
    InterfacesRemoved() = delete;
    ~InterfacesRemoved() = default;
    InterfacesRemoved(const InterfacesRemoved&) = default;
    InterfacesRemoved& operator=(const InterfacesRemoved&) = default;
    InterfacesRemoved(InterfacesRemoved&&) = default;
    InterfacesRemoved& operator=(InterfacesRemoved&&) = default;
    InterfacesRemoved(const char* path, const char* intf, U&& handler) :
        _path(path), _intf(intf), _handler(std::forward<U>(handler))
    {}

    /** @brief Run signal handler function
     *
     * Extract the interfaces from the InterfacesRemoved
     * message and run the handler function.
     */
    void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg,
                    Zone& zone) const
    {
        if (msg)
        {
            std::vector<std::string> intfs;
            sdbusplus::message::object_path op;

            msg.read(op);
            if (static_cast<const std::string&>(op) != _path)
            {
                // Object path does not match this handler's path
                return;
            }

            msg.read(intfs);
            auto itIntf = std::find(intfs.begin(), intfs.end(), _intf);
            if (itIntf == intfs.cend())
            {
                // Interface not found on this handler's path
                return;
            }

            _handler(zone);
        }
    }

  private:
    const char* _path;
    const char* _intf;
    U _handler;
};

/**
 * @brief Used to process a Dbus interfaces removed signal event
 *
 * @param[in] path - Object path
 * @param[in] intf - Object interface
 * @param[in] handler - Handler function to perform
 *
 * @tparam U - The type of the handler
 */
template <typename U>
auto interfacesRemoved(const char* path, const char* intf, U&& handler)
{
    return InterfacesRemoved<U>(path, intf, std::forward<U>(handler));
}

/**
 * @struct Name Owner
 * @brief A functor for Dbus name owner signals and methods
 *
 * @tparam U - The type of the handler
 */
template <typename U>
struct NameOwner
{
    NameOwner() = delete;
    ~NameOwner() = default;
    NameOwner(const NameOwner&) = default;
    NameOwner& operator=(const NameOwner&) = default;
    NameOwner(NameOwner&&) = default;
    NameOwner& operator=(NameOwner&&) = default;
    explicit NameOwner(U&& handler) : _handler(std::forward<U>(handler)) {}

    /** @brief Run signal handler function
     *
     * Extract the name owner from the NameOwnerChanged
     * message and run the handler function.
     */
    void operator()(sdbusplus::bus_t&, sdbusplus::message_t& msg,
                    Zone& zone) const
    {
        if (msg)
        {
            std::string name;
            bool hasOwner = false;

            // Handle NameOwnerChanged signals
            msg.read(name);

            std::string oldOwn;
            msg.read(oldOwn);

            std::string newOwn;
            msg.read(newOwn);
            if (!newOwn.empty())
            {
                hasOwner = true;
            }
            _handler(zone, name, hasOwner);
        }
    }

    void operator()(Zone& zone, const Group& group) const
    {
        std::string name = "";
        bool hasOwner = false;
        std::for_each(group.begin(), group.end(),
                      [&zone, &group, &name, &hasOwner,
                       handler = std::move(_handler)](const auto& member) {
            auto path = std::get<pathPos>(member);
            auto intf = std::get<intfPos>(member);
            try
            {
                auto servName = zone.getService(path, intf);
                if (name != servName)
                {
                    name = servName;
                    hasOwner = util::SDBusPlus::callMethodAndRead<bool>(
                        zone.getBus(), "org.freedesktop.DBus",
                        "/org/freedesktop/DBus", "org.freedesktop.DBus",
                        "NameHasOwner", name);
                    // Update service name owner state list of a group
                    handler(zone, name, hasOwner);
                }
            }
            catch (const util::DBusMethodError& e)
            {
                // Failed to get service name owner state
                name = "";
                hasOwner = false;
            }
        });
    }

  private:
    U _handler;
};

/**
 * @brief Used to process a Dbus name owner changed signal event
 *
 * @param[in] handler - Handler function to perform
 *
 * @tparam U - The type of the handler
 *
 * @return - The NameOwnerChanged signal struct
 */
template <typename U>
auto nameOwnerChanged(U&& handler)
{
    return NameOwner<U>(std::forward<U>(handler));
}

/**
 * @brief Used to process the init of a name owner event
 *
 * @param[in] handler - Handler function to perform
 *
 * @tparam U - The type of the handler
 *
 * @return - The NameOwnerChanged signal struct
 */
template <typename U>
auto nameHasOwner(U&& handler)
{
    return NameOwner<U>(std::forward<U>(handler));
}

} // namespace control
} // namespace fan
} // namespace phosphor
