#pragma once

#include "power_supply.hpp"
#include "types.hpp"
#include "utility.hpp"

#include <phosphor-logging/log.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdeventplus/event.hpp>
#include <sdeventplus/utility/timer.hpp>

using namespace phosphor::power::psu;
using namespace phosphor::logging;

namespace phosphor
{
namespace power
{
namespace manager
{

struct json_properties
{
    int pollInterval;
};

/**
 * @class PSUManager
 *
 * This class will create an object used to manage and monitor a list of power
 * supply devices.
 */
class PSUManager
{
  public:
    PSUManager() = delete;
    ~PSUManager() = default;
    PSUManager(const PSUManager&) = delete;
    PSUManager& operator=(const PSUManager&) = delete;
    PSUManager(PSUManager&&) = delete;
    PSUManager& operator=(PSUManager&&) = delete;

    /**
     * Constructor
     *
     * @param[in] bus - D-Bus bus object
     * @param[in] e - event object
     * @param[in] configfile - string path to the configuration file
     */
    PSUManager(sdbusplus::bus::bus& bus, const sdeventplus::Event& e,
               const std::string& configfile) :
        bus(bus)
    {
        // Parse out the JSON properties
        json_properties properties = {0};
        getJSONProperties(configfile, properties);

        using namespace sdeventplus;
        auto pollInterval = std::chrono::milliseconds(properties.pollInterval);
        timer = std::make_unique<utility::Timer<ClockId::Monotonic>>(
            e, std::bind(&PSUManager::analyze, this), pollInterval);

        // Subscribe to power state changes
        powerService = util::getService(POWER_OBJ_PATH, POWER_IFACE, bus);
        powerOnMatch = std::make_unique<sdbusplus::bus::match_t>(
            bus,
            sdbusplus::bus::match::rules::propertiesChanged(POWER_OBJ_PATH,
                                                            POWER_IFACE),
            [this](auto& msg) { this->powerStateChanged(msg); });

        initialize();
    }

    void getJSONProperties(const std::string& path, json_properties& p)
    {
        nlohmann::json configFileJSON = util::loadJSONFromFile(path.c_str());

        if (configFileJSON == nullptr)
        {
            throw std::runtime_error("Failed to load JSON configuration file");
        }

        if (!configFileJSON.contains("pollInterval"))
        {
            throw std::runtime_error("Missing required pollInterval property");
        }

        p.pollInterval = configFileJSON.at("pollInterval");
    }

    /**
     * Initializes the manager.
     *
     * Get current BMC state, ...
     */
    void initialize()
    {
        // When state = 1, system is powered on
        int32_t state = 0;

        try
        {
            // Use getProperty utility function to get power state.
            util::getProperty<int32_t>(POWER_IFACE, "state", POWER_OBJ_PATH,
                                       powerService, bus, state);

            if (state)
            {
                powerOn = true;
            }
            else
            {
                powerOn = false;
            }
        }
        catch (std::exception& e)
        {
            log<level::INFO>("Failed to get power state. Assuming it is off.");
            powerOn = false;
        }

        clearFaults();
        updateInventory();
    }

    /**
     * Starts the timer to start monitoring the list of devices.
     */
    int run()
    {
        return timer->get_event().loop();
    }

    /**
     * This function will be called in various situations in order to clear
     * any fault status bits that may have been set, in order to start over
     * with a clean state. Presence changes and power state changes will want
     * to clear any faults logged.
     */
    void clearFaults()
    {
        for (auto& psu : psus)
        {
            psu.clearFaults();
        }
    }

  private:
    /**
     * The D-Bus object
     */
    sdbusplus::bus::bus& bus;

    /**
     * The timer that runs to periodically check the power supplies.
     */
    std::unique_ptr<
        sdeventplus::utility::Timer<sdeventplus::ClockId::Monotonic>>
        timer;

    /**
     * Analyze the status of each of the power supplies.
     */
    void analyze()
    {
        for (auto& psu : psus)
        {
            psu.analyze();
        }
    }

    /** @brief True if the power is on. */
    bool powerOn = false;

    /** @brief Used as part of subscribing to power on state changes*/
    std::string powerService;

    /** @brief Used to subscribe to D-Bus power on state changes */
    std::unique_ptr<sdbusplus::bus::match_t> powerOnMatch;

    /**
     * @brief Callback for power state property changes
     *
     * Process changes to the powered on state property for the system.
     *
     * @param[in] msg - Data associated with the power state signal
     */
    void powerStateChanged(sdbusplus::message::message& msg);

    /**
     * @brief Adds properties to the inventory.
     *
     * Reads the values from the devices and writes them to the associated
     * power supply D-Bus inventory objects.
     *
     * This needs to be done on startup, and each time the presence state
     * changes.
     */
    void updateInventory()
    {
        for (auto& psu : psus)
        {
            psu.updateInventory();
        }
    }

    /**
     * @brief The vector for power supplies.
     */
    std::vector<PowerSupply> psus;
};

} // namespace manager
} // namespace power
} // namespace phosphor
