#include "sensor.hpp"

#include "utils/clock.hpp"

#include <boost/container/flat_map.hpp>
#include <phosphor-logging/log.hpp>
#include <sdbusplus/asio/property.hpp>

#include <functional>

Sensor::Sensor(interfaces::Sensor::Id sensorId,
               const std::string& sensorMetadata, boost::asio::io_context& ioc,
               const std::shared_ptr<sdbusplus::asio::connection>& bus) :
    sensorId(std::move(sensorId)),
    sensorMetadata(sensorMetadata), ioc(ioc), bus(bus)
{}

Sensor::Id Sensor::makeId(std::string_view service, std::string_view path)
{
    return Id("Sensor", service, path);
}

Sensor::Id Sensor::id() const
{
    return sensorId;
}

std::string Sensor::metadata() const
{
    return sensorMetadata;
}

std::string Sensor::getName() const
{
    return sensorMetadata.empty() ? sensorId.path : sensorMetadata;
}

void Sensor::async_read()
{
    uniqueCall([this](auto lock) { async_read(std::move(lock)); });
}

void Sensor::async_read(std::shared_ptr<utils::UniqueCall::Lock> lock)
{
    makeSignalMonitor();

    sdbusplus::asio::getProperty<double>(
        *bus, sensorId.service, sensorId.path,
        "xyz.openbmc_project.Sensor.Value", "Value",
        [lock, id = sensorId, weakSelf = weak_from_this()](
            boost::system::error_code ec, double newValue) {
        if (ec)
        {
            phosphor::logging::log<phosphor::logging::level::WARNING>(
                "DBus 'GetProperty' call failed on Sensor Value",
                phosphor::logging::entry("SENSOR_PATH=%s", id.path.c_str()),
                phosphor::logging::entry("ERROR_CODE=%d", ec.value()));
            return;
        }
        if (auto self = weakSelf.lock())
        {
            self->updateValue(newValue);
        }
    });
}

void Sensor::registerForUpdates(
    const std::weak_ptr<interfaces::SensorListener>& weakListener)
{
    listeners.erase(
        std::remove_if(listeners.begin(), listeners.end(),
                       [](const auto& listener) { return listener.expired(); }),
        listeners.end());

    if (auto listener = weakListener.lock())
    {
        listeners.emplace_back(weakListener);

        if (value)
        {
            listener->sensorUpdated(*this, timestamp, *value);
        }
        else
        {
            async_read();
        }
    }
}

void Sensor::unregisterFromUpdates(
    const std::weak_ptr<interfaces::SensorListener>& weakListener)
{
    if (auto listener = weakListener.lock())
    {
        listeners.erase(std::remove_if(listeners.begin(), listeners.end(),
                                       [listenerToUnregister = listener.get()](
                                           const auto& listener) {
            return (listener.expired() ||
                    listener.lock().get() == listenerToUnregister);
        }),
                        listeners.end());
    }
}

void Sensor::updateValue(double newValue)
{
    timestamp = Clock().steadyTimestamp();

    if (value != newValue)
    {
        value = newValue;

        for (const auto& weakListener : listeners)
        {
            if (auto listener = weakListener.lock())
            {
                listener->sensorUpdated(*this, timestamp, *value);
            }
        }
    }
}

void Sensor::makeSignalMonitor()
{
    if (signalMonitor)
    {
        return;
    }

    using namespace std::string_literals;

    const auto param = "type='signal',member='PropertiesChanged',path='"s +
                       sensorId.path +
                       "',arg0='xyz.openbmc_project.Sensor.Value'"s;

    signalMonitor = std::make_unique<sdbusplus::bus::match_t>(
        *bus, param,
        [weakSelf = weak_from_this()](sdbusplus::message_t& message) {
        signalProc(weakSelf, message);
    });
}

void Sensor::signalProc(const std::weak_ptr<Sensor>& weakSelf,
                        sdbusplus::message_t& message)
{
    if (auto self = weakSelf.lock())
    {
        std::string iface;
        boost::container::flat_map<std::string, ValueVariant>
            changed_properties;
        std::vector<std::string> invalidated_properties;

        message.read(iface, changed_properties, invalidated_properties);

        if (iface == "xyz.openbmc_project.Sensor.Value")
        {
            const auto it = changed_properties.find("Value");
            if (it != changed_properties.end())
            {
                if (auto val = std::get_if<double>(&it->second))
                {
                    self->updateValue(*val);
                }
                else
                {
                    phosphor::logging::log<phosphor::logging::level::ERR>(
                        "Failed to receive Value from Sensor "
                        "PropertiesChanged signal",
                        phosphor::logging::entry("SENSOR_PATH=%s",
                                                 self->sensorId.path.c_str()));
                }
            }
        }
    }
}

LabeledSensorInfo Sensor::getLabeledSensorInfo() const
{
    return LabeledSensorInfo(sensorId.service, sensorId.path, sensorMetadata);
}
