#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
