#pragma once
#include "fan.hpp"
#include "sdbusplus.hpp"
#include "types.hpp"
#include "xyz/openbmc_project/Control/ThermalMode/server.hpp"

#include <sdbusplus/bus.hpp>
#include <sdeventplus/event.hpp>

#include <algorithm>
#include <cassert>
#include <chrono>
#include <cmath>
#include <optional>
#include <vector>

namespace phosphor
{
namespace fan
{
namespace control
{

using ThermalObject = sdbusplus::server::object_t<
    sdbusplus::xyz::openbmc_project::Control::server::ThermalMode>;

/**
 * The mode fan control will run in:
 *   - init - only do the initialization steps
 *   - control - run normal control algorithms
 */
enum class Mode
{
    init,
    control
};

/**
 * @class Represents a fan control zone, which is a group of fans
 * that behave the same.
 */
class Zone : public ThermalObject
{
  public:
    Zone() = delete;
    Zone(const Zone&) = delete;
    Zone(Zone&&) = delete;
    Zone& operator=(const Zone&) = delete;
    Zone& operator=(Zone&&) = delete;
    ~Zone() = default;

    /**
     * Constructor
     * Creates the appropriate fan objects based on
     * the zone definition data passed in.
     *
     * @param[in] mode - mode of fan control
     * @param[in] bus - the dbus object
     * @param[in] path - object instance path
     * @param[in] event - Event loop reference
     * @param[in] def - the fan zone definition data
     */
    Zone(Mode mode, sdbusplus::bus_t& bus, const std::string& path,
         const sdeventplus::Event& event, const ZoneDefinition& def);

    /**
     * @brief Get the zone's bus
     *
     * @return The bus used by the zone
     */
    inline auto& getBus()
    {
        return _bus;
    }

    /**
     * @brief Get the zone's path
     *
     * @return The path of this zone
     */
    inline auto& getPath()
    {
        return _path;
    }

    /**
     * @brief Get the zone's hosted interfaces
     *
     * @return The interfaces hosted by this zone
     */
    inline auto& getIfaces()
    {
        return _ifaces;
    }

    /**
     * Sets all fans in the zone to the speed
     * passed in when the zone is active
     *
     * @param[in] speed - the fan speed
     */
    void setSpeed(uint64_t speed);

    /**
     * Sets the zone to full speed regardless of zone's active state
     */
    void setFullSpeed();

    /**
     * @brief Sets the automatic fan control allowed active state
     *
     * @param[in] group - A group that affects the active state
     * @param[in] isActiveAllow - Active state according to group
     */
    void setActiveAllow(const Group* group, bool isActiveAllow);

    /**
     * @brief Sets the floor change allowed state
     *
     * @param[in] group - A group that affects floor changes
     * @param[in] isAllow - Allow state according to group
     */
    inline void setFloorChangeAllow(const Group* group, bool isAllow)
    {
        _floorChange[*(group)] = isAllow;
    }

    /**
     * @brief Sets the decrease allowed state of a group
     *
     * @param[in] group - A group that affects speed decreases
     * @param[in] isAllow - Allow state according to group
     */
    inline void setDecreaseAllow(const Group* group, bool isAllow)
    {
        _decAllowed[*(group)] = isAllow;
    }

    /**
     * @brief Sets a given object's event data for a property on this zone
     *
     * @param[in] object - Name of the object containing the property
     * @param[in] interface - Interface name containing the property
     * @param[in] property - Property name
     * @param[in] data - Property value
     */
    inline void setObjectData(const std::string& object,
                              const std::string& interface,
                              const std::string& property, EventData* data)
    {
        _objects[object][interface][property] = data;
    }

    /**
     * @brief Sets a given object's property value
     *
     * @param[in] object - Name of the object containing the property
     * @param[in] interface - Interface name containing the property
     * @param[in] property - Property name
     * @param[in] value - Property value
     */
    template <typename T>
    void setPropertyValue(const char* object, const char* interface,
                          const char* property, T value)
    {
        _properties[object][interface][property] = value;
    }

    /**
     * @brief Sets a given object's property value
     *
     * @param[in] object - Name of the object containing the property
     * @param[in] interface - Interface name containing the property
     * @param[in] property - Property name
     * @param[in] value - Property value
     */
    template <typename T>
    void setPropertyValue(const std::string& object,
                          const std::string& interface,
                          const std::string& property, T value)
    {
        _properties[object][interface][property] = value;
    }

    /**
     * @brief Get the value of an object's property
     *
     * @param[in] object - Name of the object containing the property
     * @param[in] interface - Interface name containing the property
     * @param[in] property - Property name
     *
     * @return - The property value
     */
    template <typename T>
    inline auto getPropertyValue(const std::string& object,
                                 const std::string& interface,
                                 const std::string& property)
    {
        return std::get<T>(_properties.at(object).at(interface).at(property));
    }

    /**
     * @brief Get the object's property variant
     *
     * @param[in] object - Name of the object containing the property
     * @param[in] interface - Interface name containing the property
     * @param[in] property - Property name
     *
     * @return - The property variant
     */
    inline auto getPropValueVariant(const std::string& object,
                                    const std::string& interface,
                                    const std::string& property)
    {
        return _properties.at(object).at(interface).at(property);
    }

    /**
     * @brief Get a property's value after applying a set of visitors
     * to translate the property value's type change to keep from
     * affecting the configured use of the property.
     *
     * @param[in] intf = Interface name containing the property
     * @param[in] prop = Property name
     * @param[in] variant = Variant containing the property's value from
     *                      the supported property types.
     */
    template <typename T>
    inline auto getPropertyValueVisitor(const char* intf, const char* prop,
                                        PropertyVariantType& variant)
    {
        // Handle the transition of the dbus sensor value type from
        // int64 to double which also removed the scale property.
        // https://gerrit.openbmc-project.xyz/11739
        if (strcmp(intf, "xyz.openbmc_project.Sensor.Value") == 0 &&
            strcmp(prop, "Value") == 0)
        {
            // Use 'optional' variable to determine if the sensor value
            // is set within the visitor based on the supported types.
            // A non-supported type configured will assert.
            std::optional<T> value;
            std::visit(
                [&value](auto&& val) {
                    // If the type configured is int64, but the sensor value
                    // property's type is double, scale it by 1000 and return
                    // the value as an int64 as configured.
                    using V = std::decay_t<decltype(val)>;
                    if constexpr (std::is_same_v<T, int64_t> &&
                                  std::is_same_v<V, double>)
                    {
                        val = val * 1000;
                        value = std::lround(val);
                    }
                    // If the type configured matches the sensor value
                    // property's type, just return the value as its
                    // given type.
                    else if constexpr (std::is_same_v<T, V>)
                    {
                        value = val;
                    }
                },
                variant);

            // Unable to return Sensor Value property
            // as given type configured.
            assert(value);

            return value.value();
        }

        // Default to return the property's value by the data type
        // configured, applying no visitors to the variant.
        return std::get<T>(variant);
    }

    /**
     * @brief Remove an object's interface
     *
     * @param[in] object - Name of the object with the interface
     * @param[in] interface - Interface name to remove
     */
    inline void removeObjectInterface(const char* object, const char* interface)
    {
        auto it = _properties.find(object);
        if (it != std::end(_properties))
        {
            _properties[object].erase(interface);
        }
    }

    /**
     * @brief Remove a service associated to a group
     *
     * @param[in] group - Group associated with service
     * @param[in] name - Service name to remove
     */
    void removeService(const Group* group, const std::string& name);

    /**
     * @brief Set or update a service name owner in use
     *
     * @param[in] group - Group associated with service
     * @param[in] name - Service name
     * @param[in] hasOwner - Whether the service is owned or not
     */
    void setServiceOwner(const Group* group, const std::string& name,
                         const bool hasOwner);

    /**
     * @brief Set or update all services for a group
     *
     * @param[in] group - Group to get service names for
     */
    void setServices(const Group* group);

    /**
     * @brief Get the group's list of service names
     *
     * @param[in] group - Group to get service names for
     *
     * @return - The list of service names
     */
    inline auto getGroupServices(const Group* group)
    {
        return _services.at(*group);
    }

    /**
     * @brief Initialize a set speed event properties and actions
     *
     * @param[in] event - Set speed event
     */
    void initEvent(const SetSpeedEvent& event);

    /**
     * @brief Removes all the set speed event properties and actions
     *
     * @param[in] event - Set speed event
     */
    void removeEvent(const SetSpeedEvent& event);

    /**
     * @brief Get the default floor speed
     *
     * @return - The defined default floor speed
     */
    inline auto getDefFloor()
    {
        return _defFloorSpeed;
    }

    /**
     * @brief Set the default floor
     *
     * @param[in] speed - Speed to set the default floor to
     */
    inline void setDefFloor(uint64_t speed)
    {
        _defFloorSpeed = speed;
    }

    /**
     * @brief Get the ceiling speed
     *
     * @return - The current ceiling speed
     */
    inline auto& getCeiling() const
    {
        return _ceilingSpeed;
    }

    /**
     * @brief Set the ceiling speed to the given speed
     *
     * @param[in] speed - Speed to set the ceiling to
     */
    inline void setCeiling(uint64_t speed)
    {
        _ceilingSpeed = speed;
    }

    /**
     * @brief Swaps the ceiling key value with what's given and
     * returns the value that was swapped.
     *
     * @param[in] keyValue - New ceiling key value
     *
     * @return - Ceiling key value prior to swapping
     */
    inline auto swapCeilingKeyValue(int64_t keyValue)
    {
        std::swap(_ceilingKeyValue, keyValue);
        return keyValue;
    }

    /**
     * @brief Get the increase speed delta
     *
     * @return - The current increase speed delta
     */
    inline auto& getIncSpeedDelta() const
    {
        return _incSpeedDelta;
    }

    /**
     * @brief Get the decrease speed delta
     *
     * @return - The current decrease speed delta
     */
    inline auto& getDecSpeedDelta() const
    {
        return _decSpeedDelta;
    }

    /**
     * @brief Set the floor speed to the given speed and increase target
     * speed to the floor when target is below floor where floor changes
     * are allowed.
     *
     * @param[in] speed - Speed to set the floor to
     */
    void setFloor(uint64_t speed);

    /**
     * @brief Set the requested speed base to be used as the speed to
     * base a new requested speed target from
     *
     * @param[in] speedBase - Base speed value to use
     */
    inline void setRequestSpeedBase(uint64_t speedBase)
    {
        _requestSpeedBase = speedBase;
    }

    /**
     * @brief Calculate the requested target speed from the given delta
     * and increase the fan speeds, not going above the ceiling.
     *
     * @param[in] targetDelta - The delta to increase the target speed by
     */
    void requestSpeedIncrease(uint64_t targetDelta);

    /**
     * @brief Calculate the requested target speed from the given delta
     * and increase the fan speeds, not going above the ceiling.
     *
     * @param[in] targetDelta - The delta to increase the target speed by
     */
    void requestSpeedDecrease(uint64_t targetDelta);

    /**
     * @brief Callback function for the increase timer that delays
     * processing of requested speed increases while fans are increasing
     */
    void incTimerExpired();

    /**
     * @brief Callback function for the decrease timer that processes any
     * requested speed decreases if allowed
     */
    void decTimerExpired();

    /**
     * @brief Get the event loop used with this zone's timers
     *
     * @return - The event loop for timers
     */
    inline auto& getEventLoop()
    {
        return _eventLoop;
    }

    /**
     * @brief Remove the given signal event
     *
     * @param[in] seIter - Iterator pointing to the signal event to remove
     */
    inline void removeSignal(std::vector<SignalEvent>::iterator& seIter)
    {
        std::get<signalEventDataPos>(*seIter).reset();
        if (std::get<signalMatchPos>(*seIter) != nullptr)
        {
            std::get<signalMatchPos>(*seIter).reset();
        }
    }

    /**
     * @brief Get the list of timer events
     *
     * @return - List of timer events
     */
    inline auto& getTimerEvents()
    {
        return _timerEvents;
    }

    /**
     * @brief Find the first instance of a timer event
     *
     * @param[in] eventGroup - Group associated with a timer
     * @param[in] eventActions - List of actions associated with a timer
     * @param[in] eventTimers - List of timers to find the timer in
     *
     * @return - Iterator to the timer event
     */
    std::vector<TimerEvent>::iterator findTimer(
        const Group& eventGroup, const std::vector<Action>& eventActions,
        std::vector<TimerEvent>& eventTimers);

    /**
     * @brief Add a timer to the list of timer based events
     *
     * @param[in] name - Event name associated with timer
     * @param[in] group - Group associated with a timer
     * @param[in] actions - List of actions associated with a timer
     * @param[in] tConf - Configuration for the new timer
     */
    void addTimer(const std::string& name, const Group& group,
                  const std::vector<Action>& actions, const TimerConf& tConf);

    /**
     * @brief Callback function for event timers that processes the given
     * actions for a group
     *
     * @param[in] eventGroup - Group to process actions on
     * @param[in] eventActions - List of event actions to run
     */
    void timerExpired(const Group& eventGroup,
                      const std::vector<Action>& eventActions);

    /**
     * @brief Get the service for a given path and interface from cached
     * dataset and add a service that's not found
     *
     * @param[in] path - Path to get service for
     * @param[in] intf - Interface to get service for
     *
     * @return - The service name
     */
    const std::string& getService(const std::string& path,
                                  const std::string& intf);

    /**
     * @brief Add a set of services for a path and interface
     * by retrieving all the path subtrees to the given depth
     * from root for the interface
     *
     * @param[in] path - Path to add services for
     * @param[in] intf - Interface to add services for
     * @param[in] depth - Depth of tree traversal from root path
     *
     * @return - The associated service to the given path and interface
     * or empty string for no service found
     */
    const std::string& addServices(const std::string& path,
                                   const std::string& intf, int32_t depth);

    /**
     * @brief Dbus signal change callback handler
     *
     * @param[in] msg - Expanded sdbusplus message data
     * @param[in] eventData - The single event's data
     */
    void handleEvent(sdbusplus::message_t& msg, const EventData* eventData);

    /**
     * @brief Add a signal to the list of signal based events
     *
     * @param[in] name - Event name
     * @param[in] data - Event data for signal
     * @param[in] match - Subscribed signal match
     */
    inline void addSignal(const std::string& name,
                          std::unique_ptr<EventData>&& data,
                          std::unique_ptr<sdbusplus::bus::match_t>&& match)
    {
        _signalEvents[name].emplace_back(std::move(data), std::move(match));
    }

    /**
     * @brief Set a property to be persisted
     *
     * @param[in] intf - Interface containing property
     * @param[in] prop - Property to be persisted
     */
    inline void setPersisted(const std::string& intf, const std::string& prop)
    {
        _persisted[intf].emplace_back(prop);
    }

    /**
     * @brief Get persisted property
     *
     * @param[in] intf - Interface containing property
     * @param[in] prop - Property persisted
     *
     * @return - True if property is to be persisted, false otherwise
     */
    auto getPersisted(const std::string& intf, const std::string& prop);

    /**
     * @brief Get a property value from the zone object or the bus when
     * the property requested is not on the zone object
     *
     * @param[in] path - Path of object
     * @param[in] intf - Object interface
     * @param[in] prop - Object property
     *
     * @return - Property's value
     */
    template <typename T>
    auto getPropertyByName(const std::string& path, const std::string& intf,
                           const std::string& prop)
    {
        T value;
        auto pathIter = _objects.find(path);
        if (pathIter != _objects.end())
        {
            auto intfIter = pathIter->second.find(intf);
            if (intfIter != pathIter->second.end())
            {
                if (intf == "xyz.openbmc_project.Control.ThermalMode")
                {
                    auto var = ThermalMode::getPropertyByName(prop);
                    // Use visitor to determine if requested property
                    // type(T) is available on this interface and read it
                    std::visit(
                        [&value](auto&& val) {
                            using V = std::decay_t<decltype(val)>;
                            if constexpr (std::is_same_v<T, V>)
                            {
                                value = val;
                            }
                        },
                        var);

                    return value;
                }
            }
        }

        // Retrieve the property's value applying any visitors necessary
        auto service = getService(path, intf);
        auto variant = util::SDBusPlus::getPropertyVariant<PropertyVariantType>(
            _bus, service, path, intf, prop);
        value = getPropertyValueVisitor<T>(intf.c_str(), prop.c_str(), variant);

        return value;
    }

    /**
     * @brief Overridden thermal object's set 'Current' property function
     *
     * @param[in] value - Value to set 'Current' to
     *
     * @return - The updated value of the 'Current' property
     */
    virtual std::string current(std::string value);

  private:
    /**
     * The dbus object
     */
    sdbusplus::bus_t& _bus;

    /**
     * Zone object path
     */
    const std::string _path;

    /**
     * Zone supported interfaces
     */
    const std::vector<std::string> _ifaces;

    /**
     * Full speed for the zone
     */
    const uint64_t _fullSpeed;

    /**
     * The zone number
     */
    const size_t _zoneNum;

    /**
     * The default floor speed for the zone
     */
    uint64_t _defFloorSpeed;

    /**
     * The default ceiling speed for the zone
     */
    const uint64_t _defCeilingSpeed;

    /**
     * The floor speed to not go below
     */
    uint64_t _floorSpeed = _defFloorSpeed;

    /**
     * The ceiling speed to not go above
     */
    uint64_t _ceilingSpeed = _defCeilingSpeed;

    /**
     * The previous sensor value for calculating the ceiling
     */
    int64_t _ceilingKeyValue = 0;

    /**
     * Automatic fan control active state
     */
    bool _isActive = true;

    /**
     * Target speed for this zone
     */
    uint64_t _targetSpeed = _fullSpeed;

    /**
     * Speed increase delta
     */
    uint64_t _incSpeedDelta = 0;

    /**
     * Speed decrease delta
     */
    uint64_t _decSpeedDelta = 0;

    /**
     * Requested speed base
     */
    uint64_t _requestSpeedBase = 0;

    /**
     * Speed increase delay in seconds
     */
    std::chrono::seconds _incDelay;

    /**
     * Speed decrease interval in seconds
     */
    std::chrono::seconds _decInterval;

    /**
     * The increase timer object
     */
    Timer _incTimer;

    /**
     * The decrease timer object
     */
    Timer _decTimer;

    /**
     * Event loop used on set speed event timers
     */
    sdeventplus::Event _eventLoop;

    /**
     * The vector of fans in this zone
     */
    std::vector<std::unique_ptr<Fan>> _fans;

    /**
     * @brief Map of object property values
     */
    std::map<std::string,
             std::map<std::string, std::map<std::string, PropertyVariantType>>>
        _properties;

    /**
     * @brief Map of zone objects
     */
    std::map<std::string,
             std::map<std::string, std::map<std::string, EventData*>>>
        _objects;

    /**
     * @brief Map of interfaces to persisted properties
     */
    std::map<std::string, std::vector<std::string>> _persisted;

    /**
     * @brief Map of active fan control allowed by groups
     */
    std::map<const Group, bool> _active;

    /**
     * @brief Map of floor change allowed by groups
     */
    std::map<const Group, bool> _floorChange;

    /**
     * @brief Map of groups controlling decreases allowed
     */
    std::map<const Group, bool> _decAllowed;

    /**
     * @brief Map of group service names
     */
    std::map<const Group, std::vector<Service>> _services;

    /**
     * @brief Map tree of paths to services of interfaces
     */
    std::map<std::string, std::map<std::string, std::vector<std::string>>>
        _servTree;

    /**
     * @brief List of signal event arguments and Dbus matches
     * for callbacks per event name
     */
    std::map<std::string, std::vector<SignalEvent>> _signalEvents;

    /**
     * @brief List of timers per event name
     */
    std::map<std::string, std::vector<TimerEvent>> _timerEvents;

    /**
     * @brief Save the thermal control current mode property
     * to persisted storage
     */
    void saveCurrentMode();

    /**
     * @brief Restore persisted thermal control current mode property
     * value, setting the mode to "Default" otherwise
     */
    void restoreCurrentMode();

    /**
     * @brief Get the request speed base if defined, otherwise the
     * the current target speed is returned
     *
     * @return - The request speed base or current target speed
     */
    inline auto getRequestSpeedBase() const
    {
        return (_requestSpeedBase != 0) ? _requestSpeedBase : _targetSpeed;
    }
};

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