#include "ExternalSensor.hpp"

#include "SensorPaths.hpp"
#include "Thresholds.hpp"
#include "Utils.hpp"
#include "sensor.hpp"

#include <phosphor-logging/lg2.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>

#include <chrono>
#include <cmath>
#include <cstddef>
#include <functional>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <utility>
#include <vector>

static constexpr bool debug = false;

ExternalSensor::ExternalSensor(
    const std::string& objectType, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& conn,
    const std::string& sensorName, const std::string& sensorUnits,
    std::vector<thresholds::Threshold>&& thresholdsIn,
    const std::string& sensorConfiguration, double maxReading,
    double minReading, double timeoutSecs, const PowerState& powerState) :
    Sensor(escapeName(sensorName), std::move(thresholdsIn), sensorConfiguration,
           objectType, true, true, maxReading, minReading, conn, powerState),
    objServer(objectServer), writeLast(std::chrono::steady_clock::now()),
    writeTimeout(
        std::chrono::duration_cast<std::chrono::steady_clock::duration>(
            std::chrono::duration<double>(timeoutSecs))),
    writePerishable(timeoutSecs > 0.0)
{
    // The caller must specify what physical characteristic
    // an external sensor is expected to be measuring, such as temperature,
    // as, unlike others, this is not implied by device type name.
    std::string dbusPath = sensor_paths::getPathForUnits(sensorUnits);
    if (dbusPath.empty())
    {
        throw std::runtime_error("Units not in allow list");
    }
    std::string objectPath = "/xyz/openbmc_project/sensors/";
    objectPath += dbusPath;
    objectPath += '/';
    objectPath += name;

    sensorInterface = objectServer.add_interface(
        objectPath, "xyz.openbmc_project.Sensor.Value");

    for (const auto& threshold : thresholds)
    {
        std::string interface = thresholds::getInterface(threshold.level);
        thresholdInterfaces[static_cast<size_t>(threshold.level)] =
            objectServer.add_interface(objectPath, interface);
    }

    association =
        objectServer.add_interface(objectPath, association::interface);
    setInitialProperties(sensorUnits);

    if constexpr (debug)
    {
        lg2::error(
            "ExternalSensor '{NAME}' constructed: path '{PATH}', type '{TYPE}', "
            "min '{MIN}', max '{MAX}', timeout '{TIMEOUT}' us",
            "NAME", name, "PATH", objectPath, "TYPE", objectType, "MIN",
            minReading, "MAX", maxReading, "TIMEOUT",
            std::chrono::duration_cast<std::chrono::microseconds>(writeTimeout)
                .count());
    }
}

// Separate function from constructor, because of a gotcha: can't use the
// enable_shared_from_this() API until after the constructor has completed.
void ExternalSensor::initWriteHook(
    std::function<void(std::chrono::steady_clock::time_point now)>&&
        writeHookIn)
{
    // Connect ExternalSensorMain with ExternalSensor
    writeHook = std::move(writeHookIn);

    // Connect ExternalSensor with Sensor
    auto weakThis = weak_from_this();
    externalSetHook = [weakThis]() {
        auto lockThis = weakThis.lock();
        if (lockThis)
        {
            lockThis->externalSetTrigger();
            return;
        }
        if constexpr (debug)
        {
            lg2::error("ExternalSensor receive ignored, sensor gone");
        }
    };
}

ExternalSensor::~ExternalSensor()
{
    // Make sure the write hook does not reference this object anymore
    externalSetHook = nullptr;

    objServer.remove_interface(association);
    for (const auto& iface : thresholdInterfaces)
    {
        objServer.remove_interface(iface);
    }
    objServer.remove_interface(sensorInterface);

    if constexpr (debug)
    {
        lg2::error("ExternalSensor '{NAME}' destructed", "NAME", name);
    }
}

void ExternalSensor::checkThresholds()
{
    thresholds::checkThresholds(this);
}

bool ExternalSensor::isAliveAndPerishable() const
{
    return (writeAlive && writePerishable);
}

bool ExternalSensor::isAliveAndFresh(
    const std::chrono::steady_clock::time_point& now) const
{
    // Must be alive and perishable, to have possibility of being fresh
    if (!isAliveAndPerishable())
    {
        return false;
    }

    // If age, as of now, is less than timeout, it is deemed fresh
    // NOLINTNEXTLINE
    return (ageElapsed(now) < writeTimeout);
}

void ExternalSensor::writeBegin(
    const std::chrono::steady_clock::time_point& now)
{
    if (!writeAlive)
    {
        lg2::error(
            "ExternalSensor '{NAME}' online, receiving first value '{VALUE}'",
            "NAME", name, "VALUE", value);
    }

    writeLast = now;
    writeAlive = true;
}

void ExternalSensor::writeInvalidate()
{
    writeAlive = false;

    lg2::error("ExternalSensor '{NAME}' offline, timed out", "NAME", name);

    // Take back control of this sensor from the external override,
    // as the external source has timed out.
    // This allows sensor::updateValue() to work normally,
    // as it would do for internal sensors with values from hardware.
    overriddenState = false;

    // Invalidate the existing Value, similar to what internal sensors do,
    // when they encounter errors trying to read from hardware.
    updateValue(std::numeric_limits<double>::quiet_NaN());
}

std::chrono::steady_clock::duration ExternalSensor::ageElapsed(
    const std::chrono::steady_clock::time_point& now) const
{
    // Comparing 2 time_point will return duration
    return (now - writeLast);
}

std::chrono::steady_clock::duration ExternalSensor::ageRemaining(
    const std::chrono::steady_clock::time_point& now) const
{
    // Comparing duration will return another duration
    return (writeTimeout - ageElapsed(now));
}

void ExternalSensor::externalSetTrigger()
{
    if constexpr (debug)
    {
        lg2::error("ExternalSensor '{NAME}' received '{VALUE}'", "NAME", name,
                   "VALUE", value);
    }

    if (std::isfinite(value))
    {
        markAvailable(true);
    }

    auto now = std::chrono::steady_clock::now();

    writeBegin(now);

    // Tell the owner to recalculate the expiration timer
    writeHook(now);
}
