#include "config.h"

#include "sensor.hpp"

#include "env.hpp"
#include "gpio_handle.hpp"
#include "hwmon.hpp"
#include "sensorset.hpp"
#include "sysfs.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Sensor/Device/error.hpp>

#include <cassert>
#include <chrono>
#include <cmath>
#include <cstring>
#include <filesystem>
#include <format>
#include <future>
#include <thread>

namespace sensor
{

using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;

// todo: this can be simplified once we move to the double interface
Sensor::Sensor(const SensorSet::key_type& sensor,
               const hwmonio::HwmonIOInterface* ioAccess,
               const std::string& devPath) :
    _sensor(sensor),
    _ioAccess(ioAccess), _devPath(devPath), _scale(0), _hasFaultFile(false)
{
    auto chip = env::getEnv("GPIOCHIP", sensor);
    auto access = env::getEnv("GPIO", sensor);
    if (!access.empty() && !chip.empty())
    {
        _handle = gpio::BuildGpioHandle(chip, access);

        if (!_handle)
        {
            log<level::ERR>("Unable to set up gpio locking");
            elog<InternalFailure>();
        }
    }

    auto gain = env::getEnv("GAIN", sensor);
    if (!gain.empty())
    {
        _sensorAdjusts.gain = std::stod(gain);
    }

    auto offset = env::getEnv("OFFSET", sensor);
    if (!offset.empty())
    {
        _sensorAdjusts.offset = std::stoi(offset);
    }
    auto senRmRCs = env::getEnv("REMOVERCS", sensor);
    // Add sensor removal return codes defined per sensor
    addRemoveRCs(senRmRCs);
}

void Sensor::addRemoveRCs(const std::string& rcList)
{
    if (rcList.empty())
    {
        return;
    }

    // Convert to a char* for strtok
    std::vector<char> rmRCs(rcList.c_str(), rcList.c_str() + rcList.size() + 1);
    auto rmRC = std::strtok(&rmRCs[0], ", ");
    while (rmRC != nullptr)
    {
        try
        {
            _sensorAdjusts.rmRCs.insert(std::stoi(rmRC));
        }
        catch (const std::logic_error& le)
        {
            // Unable to convert to int, continue to next token
            std::string name = _sensor.first + "_" + _sensor.second;
            log<level::INFO>("Unable to convert sensor removal return code",
                             entry("SENSOR=%s", name.c_str()),
                             entry("RC=%s", rmRC),
                             entry("EXCEPTION=%s", le.what()));
        }
        rmRC = std::strtok(nullptr, ", ");
    }
}

SensorValueType Sensor::adjustValue(SensorValueType value)
{
// Because read doesn't have an out pointer to store errors.
// let's assume negative values are errors if they have this
// set.
#if NEGATIVE_ERRNO_ON_FAIL
    if (value < 0)
    {
        return value;
    }
#endif

    // Adjust based on gain and offset
    value = static_cast<decltype(value)>(static_cast<double>(value) *
                                             _sensorAdjusts.gain +
                                         _sensorAdjusts.offset);

    if constexpr (std::is_same<SensorValueType, double>::value)
    {
        value *= std::pow(10, _scale);
    }

    return value;
}

std::shared_ptr<ValueObject> Sensor::addValue(const RetryIO& retryIO,
                                              ObjectInfo& info,
                                              TimedoutMap& timedoutMap)
{
    // Get the initial value for the value interface.
    auto& bus = *std::get<sdbusplus::bus_t*>(info);
    auto& obj = std::get<InterfaceMap>(info);
    auto& objPath = std::get<std::string>(info);

    SensorValueType val = 0;

    auto& statusIface = std::any_cast<std::shared_ptr<StatusObject>&>(
        obj[InterfaceType::STATUS]);
    // As long as addStatus is called before addValue, statusIface
    // should never be nullptr
    assert(statusIface);

    // Only read the input value if the status is functional
    if (statusIface->functional())
    {
#if UPDATE_FUNCTIONAL_ON_FAIL
        try
#endif
        {
            // RAII object for GPIO unlock / lock
            auto locker = gpioUnlock(getGpio());

            // For sensors with attribute ASYNC_READ_TIMEOUT,
            // spawn a thread with timeout
            auto asyncReadTimeout = env::getEnv("ASYNC_READ_TIMEOUT", _sensor);
            if (!asyncReadTimeout.empty())
            {
                std::chrono::milliseconds asyncTimeout{
                    std::stoi(asyncReadTimeout)};
                val = asyncRead(_sensor, _ioAccess, asyncTimeout, timedoutMap,
                                _sensor.first, _sensor.second,
                                hwmon::entry::cinput, std::get<size_t>(retryIO),
                                std::get<std::chrono::milliseconds>(retryIO));
            }
            else
            {
                // Retry for up to a second if device is busy
                // or has a transient error.
                val = _ioAccess->read(
                    _sensor.first, _sensor.second, hwmon::entry::cinput,
                    std::get<size_t>(retryIO),
                    std::get<std::chrono::milliseconds>(retryIO));
            }
        }
#if UPDATE_FUNCTIONAL_ON_FAIL
        catch (const std::system_error& e)
        {
            // Catch the exception here and update the functional property.
            // By catching the exception, it will not propagate it up the stack
            // and thus the code will skip the "Remove RCs" check in
            // MainLoop::getObject and will not exit on failure.
            statusIface->functional(false);
        }
#endif
    }

    auto iface = std::make_shared<ValueObject>(bus, objPath.c_str(),
                                               ValueObject::action::defer_emit);

    hwmon::Attributes attrs;
    if (hwmon::getAttributes(_sensor.first, attrs))
    {
        iface->unit(hwmon::getUnit(attrs));

        _scale = hwmon::getScale(attrs);
    }

    val = adjustValue(val);
    iface->value(val);

    auto maxValue = env::getEnv("MAXVALUE", _sensor);
    if (!maxValue.empty())
    {
        iface->maxValue(std::stoll(maxValue));
    }
    auto minValue = env::getEnv("MINVALUE", _sensor);
    if (!minValue.empty())
    {
        iface->minValue(std::stoll(minValue));
    }

    obj[InterfaceType::VALUE] = iface;
    return iface;
}

std::shared_ptr<StatusObject> Sensor::addStatus(ObjectInfo& info)
{
    namespace fs = std::filesystem;

    std::shared_ptr<StatusObject> iface = nullptr;
    auto& objPath = std::get<std::string>(info);
    auto& obj = std::get<InterfaceMap>(info);

    // Check if fault sysfs file exists
    std::string faultName = _sensor.first;
    std::string faultID = _sensor.second;
    std::string entry = hwmon::entry::fault;

    bool functional = true;
    auto sysfsFullPath = sysfs::make_sysfs_path(_ioAccess->path(), faultName,
                                                faultID, entry);
    if (fs::exists(sysfsFullPath))
    {
        _hasFaultFile = true;
        try
        {
            uint32_t fault = _ioAccess->read(faultName, faultID, entry,
                                             hwmonio::retries, hwmonio::delay);
            if (fault != 0)
            {
                functional = false;
            }
        }
        catch (const std::system_error& e)
        {
            using namespace sdbusplus::xyz::openbmc_project::Sensor::Device::
                Error;
            using metadata = xyz::openbmc_project::Sensor::Device::ReadFailure;

            report<ReadFailure>(
                metadata::CALLOUT_ERRNO(e.code().value()),
                metadata::CALLOUT_DEVICE_PATH(_devPath.c_str()));

            log<level::INFO>(std::format("Failing sysfs file: {} errno {}",
                                         sysfsFullPath, e.code().value())
                                 .c_str());
        }
    }

    auto& bus = *std::get<sdbusplus::bus_t*>(info);

    iface = std::make_shared<StatusObject>(
        bus, objPath.c_str(), StatusObject::action::emit_no_signals);
    // Set functional property
    iface->functional(functional);

    obj[InterfaceType::STATUS] = iface;

    return iface;
}

std::shared_ptr<AccuracyObject> Sensor::addAccuracy(ObjectInfo& info,
                                                    double accuracy)
{
    auto& objPath = std::get<std::string>(info);
    auto& obj = std::get<InterfaceMap>(info);

    auto& bus = *std::get<sdbusplus::bus_t*>(info);
    auto iface = std::make_shared<AccuracyObject>(
        bus, objPath.c_str(), AccuracyObject::action::emit_no_signals);

    iface->accuracy(accuracy);
    obj[InterfaceType::ACCURACY] = iface;

    return iface;
}

std::shared_ptr<PriorityObject> Sensor::addPriority(ObjectInfo& info,
                                                    size_t priority)
{
    auto& objPath = std::get<std::string>(info);
    auto& obj = std::get<InterfaceMap>(info);

    auto& bus = *std::get<sdbusplus::bus_t*>(info);
    auto iface = std::make_shared<PriorityObject>(
        bus, objPath.c_str(), PriorityObject::action::emit_no_signals);

    iface->priority(priority);
    obj[InterfaceType::PRIORITY] = iface;

    return iface;
}

void gpioLock(const gpioplus::HandleInterface*&& handle)
{
    handle->setValues({0});
}

std::optional<GpioLocker> gpioUnlock(const gpioplus::HandleInterface* handle)
{
    if (handle == nullptr)
    {
        return std::nullopt;
    }

    handle->setValues({1});
    // Default pause needed to guarantee sensors are ready
    std::this_thread::sleep_for(std::chrono::milliseconds(500));
    return GpioLocker(std::move(handle));
}

SensorValueType asyncRead(const SensorSet::key_type& sensorSetKey,
                          const hwmonio::HwmonIOInterface* ioAccess,
                          std::chrono::milliseconds asyncTimeout,
                          TimedoutMap& timedoutMap, const std::string& type,
                          const std::string& id, const std::string& sensor,
                          const size_t retries,
                          const std::chrono::milliseconds delay)
{
    // Default async read timeout
    bool valueIsValid = false;
    std::future<int64_t> asyncThread;

    auto asyncIter = timedoutMap.find(sensorSetKey);
    if (asyncIter == timedoutMap.end())
    {
        // If sensor not found in timedoutMap, spawn an async thread
        asyncThread = std::async(std::launch::async,
                                 &hwmonio::HwmonIOInterface::read, ioAccess,
                                 type, id, sensor, retries, delay);
        valueIsValid = true;
    }
    else
    {
        // If we already have the async thread in the timedoutMap, it means this
        // sensor has already timed out in the previous reads. No need to wait
        // on subsequent reads - proceed to check the future_status to see when
        // the async thread finishes
        asyncTimeout = std::chrono::seconds(0);
        asyncThread = std::move(asyncIter->second);
    }

    // TODO: This is still not a true asynchronous read as it still blocks the
    // main thread for asyncTimeout amount of time. To make this completely
    // asynchronous, schedule a read and register a callback to update the
    // sensor value
    std::future_status status = asyncThread.wait_for(asyncTimeout);
    switch (status)
    {
        case std::future_status::ready:
            // Read has finished
            if (valueIsValid)
            {
                return asyncThread.get();
                // Good sensor reads should skip the code below
            }
            // Async read thread has completed but had previously timed out (was
            // found in the timedoutMap). Erase from timedoutMap and throw to
            // allow retry in the next read cycle. Not returning the read value
            // as the sensor reading may be bad / corrupted if it took so long.
            timedoutMap.erase(sensorSetKey);
            throw AsyncSensorReadTimeOut();
        default:
            // Read timed out so add the thread to the timedoutMap (if the entry
            // already exists, operator[] updates it).
            //
            // Keeping the timed out futures in a map is required to prevent
            // their destructor from being called when returning from this
            // stack. The destructor will otherwise block until the read
            // completes due to the limitation of std::async.
            timedoutMap[sensorSetKey] = std::move(asyncThread);
            throw AsyncSensorReadTimeOut();
    }
}

} // namespace sensor
