#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
