/**
 * Copyright © 2020 IBM Corporation
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#pragma once

#include "config_base.hpp"
#include "dbus_zone.hpp"
#include "fan.hpp"

#include <nlohmann/json.hpp>
#include <sdeventplus/event.hpp>
#include <sdeventplus/utility/timer.hpp>

#include <any>
#include <chrono>
#include <functional>
#include <map>
#include <memory>
#include <tuple>

namespace phosphor::fan::control::json
{

class Manager;

using json = nlohmann::json;

/* Dbus event timer */
using Timer = sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>;

/**
 * @class Zone - Represents a configured fan control zone
 *
 * A zone object contains the configured attributes for a zone that groups
 * a number of fans together to be under the same target control. These
 * configuration attributes include, but are not limited to, the default ceiling
 * of the fans within the zone, a default floor, the delay between increases, a
 * decrease interval, and any profiles(OPTIONAL) the zone should be included in.
 *
 * (When no profile for a zone is given, the zone defaults to always exist)
 *
 */
class Zone : public ConfigBase
{
  public:
    /* JSON file name for zones */
    static constexpr auto confFileName = "zones.json";

    Zone() = delete;
    Zone(const Zone&) = delete;
    Zone(Zone&&) = delete;
    Zone& operator=(const Zone&) = delete;
    Zone& operator=(Zone&&) = delete;
    ~Zone() = default;

    /**
     * Constructor
     * Parses and populates a zone from JSON object data
     *
     * @param[in] jsonObj - JSON object
     * @param[in] event - sdeventplus event loop
     * @param[in] mgr - Manager of this zone
     */
    Zone(const json& jsonObj, const sdeventplus::Event& event, Manager* mgr);

    /**
     * @brief Get the poweron target
     *
     * Poweron target is the target the fans within this zone should be set to
     * when the system is powered on.
     *
     * @return Poweron target of this zone
     */
    inline const auto& getPoweronTarget() const
    {
        return _poweronTarget;
    }

    /**
     * @brief Get the default ceiling
     *
     * Default ceiling is the highest target the fans within this zone is
     * allowed to increase to. The zone's ceiling defaults to this unless
     * changed by some configured event.
     *
     * @return Default ceiling of this zone
     */
    inline const auto& getDefaultCeiling() const
    {
        return _defaultCeiling;
    }

    /**
     * @brief Get the default floor
     *
     * The default floor is the lowest target the fans within this zone
     * are allowed to decrease to. The zone's floor defaults to this
     * unless changed by some configured event.
     *
     * @return Default floor
     */
    inline const auto& getDefaultFloor() const
    {
        return _defaultFloor;
    }

    /**
     * @brief Get the increase delay(OPTIONAL)
     *
     * The increase delay is the amount of time(in seconds) increases
     * to a target are delayed before being made. The default is 0, which
     * results in immediate increase requests when any events result in
     * a change to the target.
     *
     * It is recommend a value other than 0 is configured, but that inherently
     * depends on the fan controller and configured increases.
     *
     * @return Increase delay(in seconds)
     */
    inline const auto& getIncDelay() const
    {
        return _incDelay;
    }

    /**
     * @brief Get the decrease interval
     *
     * Decreases happen on a set interval when no requests for an increase
     * in fan targets exists. This is the interval(in seconds) at which the fans
     * within the zone are decreased if events exist that result in a target
     * decrease.
     *
     * @return Decrease interval(in seconds)
     */
    inline const auto& getDecInterval() const
    {
        return _decInterval;
    }

    /**
     * @brief Get the current target of the zone
     *
     * @return - The current target of the zone
     */
    inline const auto& getTarget() const
    {
        return _target;
    }

    /**
     * @brief Get the target increase delta
     *
     * @return - The current target increase delta
     */
    inline auto& getIncDelta() const
    {
        return _incDelta;
    };

    /**
     * @brief Get the target decrease delta
     *
     * @return - The current target decrease delta
     */
    inline auto& getDecDelta() const
    {
        return _decDelta;
    };

    /**
     * @brief Get the manager of the zone
     *
     * @return - The manager of the zone
     */
    inline auto* getManager() const
    {
        return _manager;
    }

    /**
     * @brief Enable the zone
     *
     * Performs the necessary tasks to enable the zone such as restoring any
     * dbus property states(if persisted), starting the decrement timer, etc...
     */
    void enable();

    /**
     * @brief Add a fan object to the zone
     *
     * @param[in] fan - Unique pointer to a fan object that will be moved into
     * the zone
     *
     * Adds a fan object to the list of fans that make up the zone by moving the
     * fan object into the list.
     */
    void addFan(std::unique_ptr<Fan> fan);

    /**
     * Sets all fans in the zone to the target given when the zone is active
     *
     * @param[in] target - Target for fans
     */
    void setTarget(uint64_t target);

    /**
     * @brief Sets the automatic fan control allowed active state
     *
     * @param[in] ident - An identifier that affects the active state
     * @param[in] isActiveAllow - Active state according to group
     */
    void setActiveAllow(const std::string& ident, bool isActiveAllow);

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

    /**
     * @brief Set the default floor to the given value
     *
     * @param[in] value - Value to set the default floor to
     */
    inline void setDefaultFloor(uint64_t value)
    {
        _defaultFloor = value;
    }

    /**
     * @brief Sets the floor change allowed state
     *
     * @param[in] ident - An identifier that affects floor changes
     * @param[in] isAllow - Allow state according to the identifier
     */
    inline void setFloorChangeAllow(const std::string& ident, bool isAllow)
    {
        _floorChange[ident] = isAllow;
    }

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

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

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

    /**
     * @brief Calculate the lowest requested decrease target from the given
     * delta within a decrease interval.
     *
     * @param[in] targetDelta - The delta to decrease the target by
     */
    void requestDecrease(uint64_t targetDelta);

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

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

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

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

    /**
     * @brief A handler function to set/update a property on a zone
     * @details Sets or updates a zone's dbus property to the given value using
     * the provided base dbus object's set property function
     *
     * @param[in] intf - Interface on zone object
     * @param[in] prop - Property on interface
     * @param[in] func - Zone dbus object's set property function pointer
     * @param[in] value - Value to set property to
     * @param[in] persist - Persist property value or not
     *
     * @return Lambda function
     *     A lambda function to set/update the zone dbus object's property
     */
    template <typename T>
    static auto setProperty(const char* intf, const char* prop,
                            T (DBusZone::*func)(T), T&& value, bool persist)
    {
        return [=, value = std::forward<T>(value)](DBusZone& dbusZone,
                                                   Zone& zone) {
            (dbusZone.*func)(value);
            if (persist)
            {
                zone.setPersisted(intf, prop);
            }
        };
    }

    /**
     * @brief A handler function to set/update a zone's dbus property's persist
     * state
     * @details Sets or updates a zone's dbus property's persist state where the
     * value of the property is to be left unchanged
     *
     * @param[in] intf - Interface on zone object
     * @param[in] prop - Property on interface
     * @param[in] persist - Persist property value or not
     *
     * @return Lambda function
     *     A lambda function to set/update the zone's dbus object's property's
     * persist state
     */
    static auto setPropertyPersist(const char* intf, const char* prop,
                                   bool persist)
    {
        return [=](DBusZone&, Zone& zone) {
            if (persist)
            {
                zone.setPersisted(intf, prop);
            }
        };
    }

  private:
    /* The zone's associated dbus object */
    std::unique_ptr<DBusZone> _dbusZone;

    /* The zone's manager */
    Manager* _manager;

    /* The zone's poweron target value for fans */
    uint64_t _poweronTarget;

    /* The zone's default ceiling value for fans */
    uint64_t _defaultCeiling;

    /* The zone's default floor value for fans */
    uint64_t _defaultFloor;

    /* Zone's increase delay(in seconds) (OPTIONAL) */
    std::chrono::seconds _incDelay;

    /* Zone's decrease interval(in seconds) (OPTIONAL) */
    std::chrono::seconds _decInterval;

    /* The floor target to not go below */
    uint64_t _floor;

    /* Target for this zone */
    uint64_t _target;

    /* Zone increase delta */
    uint64_t _incDelta;

    /* Zone decrease delta */
    uint64_t _decDelta;

    /* The ceiling target to not go above */
    uint64_t _ceiling;

    /* Requested target base */
    uint64_t _requestTargetBase;

    /* Map of whether floor changes are allowed by a string identifier */
    std::map<std::string, bool> _floorChange;

    /* Map of controlling decreases allowed by a string identifer */
    std::map<std::string, bool> _decAllowed;

    /* Map of interfaces to persisted properties the zone hosts*/
    std::map<std::string, std::vector<std::string>> _propsPersisted;

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

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

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

    /* Map of active fan control allowed by a string identifier */
    std::map<std::string, bool> _active;

    /* Interface to property mapping of their associated set property handler
     * function */
    static const std::map<
        std::string,
        std::map<std::string, std::function<std::function<void(
                                  DBusZone&, Zone&)>(const json&, bool)>>>
        _intfPropHandlers;

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

    /* List of configured interface set property functions */
    std::vector<std::function<void(DBusZone&, Zone&)>> _propInitFunctions;

    /**
     * @brief Parse and set the zone's poweron target value
     *
     * @param[in] jsonObj - JSON object for the zone
     *
     * Sets the poweron target value for the zone from the JSON configuration
     * object
     */
    void setPowerOnTarget(const json& jsonObj);

    /**
     * @brief Parse and set the interfaces served by the zone(OPTIONAL)
     *
     * @param[in] jsonObj - JSON object for the zone
     *
     * Constructs any zone interface handler functions for interfaces that the
     * zone serves which contains the interface's property's value and
     * persistency state (OPTIONAL). A property's "persist" state is defaulted
     * to not be persisted when not given.
     */
    void setInterfaces(const json& jsonObj);

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

/**
 * Properties of interfaces supported by the zone configuration
 */
namespace zone::property
{

/**
 * @brief "Supported" property on the "xyz.openbmc_project.Control.ThermalMode"
 * interface parser. Also creates the handler function for the Zone dbus object
 * to initialize the property according to what's parsed from the configuration.
 *
 * @param[in] jsonObj - JSON object for the "Supported" property
 * @param[in] persist - Whether to persist the value or not
 *
 * @return Zone dbus object's set property function for the "Supported" property
 */
std::function<void(DBusZone&, Zone&)> supported(const json& jsonObj,
                                                bool persist);

/**
 * @brief "Current" property on the "xyz.openbmc_project.Control.ThermalMode"
 * interface parser. Also creates the handler function for the Zone dbus object
 * to initialize the property according to what's parsed from the configuration.
 *
 * @param[in] jsonObj - JSON object for the "Current" property
 * @param[in] persist - Whether to persist the value or not
 *
 * @return Zone dbus object's set property function for the "Current" property
 */
std::function<void(DBusZone&, Zone&)> current(const json& jsonObj,
                                              bool persist);

} // namespace zone::property

} // namespace phosphor::fan::control::json
