#include "NVMeBasicContext.hpp"

#include "NVMeContext.hpp"
#include "NVMeSensor.hpp"

#include <sys/ioctl.h>
#include <unistd.h>

#include <FileHandle.hpp>
#include <boost/asio/buffer.hpp>
#include <boost/asio/error.hpp>
#include <boost/asio/io_context.hpp>
#include <boost/asio/read.hpp>
#include <boost/asio/streambuf.hpp>
#include <boost/asio/write.hpp>
#include <phosphor-logging/lg2.hpp>
#include <phosphor-logging/lg2/flags.hpp>

#include <array>
#include <cerrno>
#include <chrono>
#include <cmath>
#include <cstdint>
#include <cstdio>
#include <cstring>
#include <filesystem>
#include <iostream>
#include <iterator>
#include <limits>
#include <memory>
#include <stdexcept>
#include <string>
#include <system_error>
#include <thread>
#include <utility>
#include <vector>

extern "C"
{
#include <i2c/smbus.h>
#include <linux/i2c-dev.h>
}

/*
 * NVMe-MI Basic Management Command
 *
 * https://nvmexpress.org/wp-content/uploads/NVMe_Management_-_Technical_Note_on_Basic_Management_Command.pdf
 */

struct BasicQueryCmd
{
    int bus;
    uint8_t device;
    uint8_t offset;
    bool smbusPEC;
};

static void execBasicQuery(int bus, uint8_t addr, uint8_t cmd, bool smbusPEC,
                           std::vector<uint8_t>& resp)
{
    int32_t size = 0;
    std::filesystem::path devpath = "/dev/i2c-" + std::to_string(bus);

    try
    {
        FileHandle fileHandle(devpath);

        /* Select the target device */
        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
        if (::ioctl(fileHandle.handle(), I2C_SLAVE, addr) == -1)
        {
            lg2::error(
                "Failed to configure device address '{ADDR}' for bus '{BUS}': '{ERRNO}'",
                "ADDR", lg2::hex, addr, "BUS", bus, "ERRNO", lg2::hex, errno);
            resp.resize(0);
            return;
        }

        if (smbusPEC)
        {
            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
            if (::ioctl(fileHandle.handle(), I2C_PEC, 1) < 0)
            {
                lg2::error(
                    "Could not set PEC to device '{ADDR}' for bus '{BUS}': '{ERRNO}'",
                    "ADDR", lg2::hex, addr, "BUS", bus, "ERRNO", errno);
                return;
            }
        }

        resp.resize(UINT8_MAX + 1);

        /* Issue the NVMe MI basic command */
        size = i2c_smbus_read_block_data(fileHandle.handle(), cmd, resp.data());
        if (size < 0)
        {
            lg2::error(
                "Failed to read block data from device '{ADDR}' on bus '{BUS}': ERRNO",
                "ADDR", lg2::hex, addr, "BUS", bus, "ERRNO", lg2::hex, errno);
            resp.resize(0);
        }
        else if (size > UINT8_MAX + 1)
        {
            lg2::error(
                "Unexpected message length from device '{ADDR}' on bus '{BUS}': '{SIZE}' ({MAX})",
                "ADDR", lg2::hex, addr, "BUS", bus, "SIZE", size, "MAX",
                UINT8_MAX);
            resp.resize(0);
        }
        else
        {
            resp.resize(size);
        }
    }
    catch (const std::out_of_range& e)
    {
        lg2::error("Failed to create file handle for bus '{BUS}': '{ERR}'",
                   "BUS", bus, "ERR", e);
        resp.resize(0);
    }
}

static ssize_t processBasicQueryStream(FileHandle& in, FileHandle& out)
{
    std::vector<uint8_t> resp{};
    ssize_t rc = 0;

    while (true)
    {
        uint8_t len = 0;
        BasicQueryCmd req{};

        /* Read the command parameters */
        ssize_t rc = ::read(in.handle(), &req, sizeof(req));
        if (rc != static_cast<ssize_t>(sizeof(req)))
        {
            lg2::error(
                "Failed to read request from in descriptor '{ERROR_MESSAGE}'",
                "ERROR_MESSAGE", strerror(errno));
            if (rc != 0)
            {
                return -errno;
            }
            return -EIO;
        }

        /* Execute the query */
        execBasicQuery(req.bus, req.device, req.offset, req.smbusPEC, resp);

        /* Write out the response length */
        len = resp.size();
        rc = ::write(out.handle(), &len, sizeof(len));
        if (rc != sizeof(len))
        {
            lg2::error(
                "Failed to write block ({LEN}) length to out descriptor: '{ERRNO}'",
                "LEN", len, "ERRNO", strerror(static_cast<int>(-rc)));
            if (rc != 0)
            {
                return -errno;
            }
            return -EIO;
        }

        /* Write out the response data */
        std::vector<uint8_t>::iterator cursor = resp.begin();
        while (cursor != resp.end())
        {
            size_t lenRemaining = std::distance(cursor, resp.end());
            ssize_t egress = ::write(out.handle(), &(*cursor), lenRemaining);
            if (egress == -1)
            {
                lg2::error(
                    "Failed to write block data of length '{LEN}' to out pipe: '{ERROR_MESSAGE}'",
                    "LEN", lenRemaining, "ERROR_MESSAGE", strerror(errno));
                if (rc != 0)
                {
                    return -errno;
                }
                return -EIO;
            }

            cursor += egress;
        }
    }

    return rc;
}

/* Throws std::error_code on failure */
/* FIXME: Probably shouldn't do fallible stuff in a constructor */
NVMeBasicContext::NVMeBasicContext(boost::asio::io_context& io, int rootBus) :
    NVMeContext::NVMeContext(io, rootBus), io(io), reqStream(io), respStream(io)
{
    std::array<int, 2> responsePipe{};
    std::array<int, 2> requestPipe{};

    /* Set up inter-thread communication */
    if (::pipe(requestPipe.data()) == -1)
    {
        lg2::error("Failed to create request pipe: '{ERROR}'", "ERROR",
                   strerror(errno));
        throw std::error_code(errno, std::system_category());
    }

    if (::pipe(responsePipe.data()) == -1)
    {
        lg2::error("Failed to create response pipe: '{ERROR}'", "ERROR",
                   strerror(errno));

        if (::close(requestPipe[0]) == -1)
        {
            lg2::error("Failed to close write fd of request pipe '{ERROR}'",
                       "ERROR", strerror(errno));
        }

        if (::close(requestPipe[1]) == -1)
        {
            lg2::error("Failed to close read fd of request pipe '{ERROR}'",
                       "ERROR", strerror(errno));
        }

        throw std::error_code(errno, std::system_category());
    }

    reqStream.assign(requestPipe[1]);
    FileHandle streamIn(requestPipe[0]);
    FileHandle streamOut(responsePipe[1]);
    respStream.assign(responsePipe[0]);

    thread = std::jthread([streamIn{std::move(streamIn)},
                           streamOut{std::move(streamOut)}]() mutable {
        ssize_t rc = processBasicQueryStream(streamIn, streamOut);

        if (rc < 0)
        {
            lg2::error("Failure while processing query stream: '{ERROR}'",
                       "ERROR", strerror(static_cast<int>(-rc)));
        }

        lg2::error("Terminating basic query thread");
    });
}

void NVMeBasicContext::readAndProcessNVMeSensor()
{
    if (pollCursor == sensors.end())
    {
        this->pollNVMeDevices();
        return;
    }

    std::shared_ptr<NVMeSensor> sensor = *pollCursor++;

    if (!sensor->readingStateGood())
    {
        sensor->markAvailable(false);
        sensor->updateValue(std::numeric_limits<double>::quiet_NaN());
        readAndProcessNVMeSensor();
        return;
    }

    /* Potentially defer sampling the sensor sensor if it is in error */
    if (!sensor->sample())
    {
        readAndProcessNVMeSensor();
        return;
    }

    if (sensor->bus < 0)
    {
        throw std::domain_error("Invalid bus argument");
    }

    BasicQueryCmd tmpCmd = {sensor->bus, sensor->address, 0x00,
                            sensor->smbusPEC};
    auto command = std::make_shared<BasicQueryCmd>(tmpCmd);

    /* Issue the request */
    boost::asio::async_write(
        reqStream, boost::asio::buffer(command.get(), sizeof(*command)),
        [command](boost::system::error_code ec, std::size_t) {
            if (ec)
            {
                lg2::error("Got error writing basic query: '{ERROR_MESSAGE}'",
                           "ERROR_MESSAGE", ec.message());
            }
        });

    auto response = std::make_shared<boost::asio::streambuf>();
    response->prepare(1);

    /* Gather the response and dispatch for parsing */
    boost::asio::async_read(
        respStream, *response,
        [response](const boost::system::error_code& ec, std::size_t n) {
            if (ec)
            {
                lg2::error(
                    "Got error completing basic query: '{ERROR_MESSAGE}'",
                    "ERROR_MESSAGE", ec.message());
                return static_cast<std::size_t>(0);
            }

            if (n == 0)
            {
                return static_cast<std::size_t>(1);
            }

            std::istream is(response.get());
            size_t len = static_cast<std::size_t>(is.peek());

            if (n > len + 1)
            {
                lg2::error(
                    "Query stream has become unsynchronised: n: {N}, len: {LEN}",
                    "N", n, "LEN", len);
                return static_cast<std::size_t>(0);
            }

            if (n == len + 1)
            {
                return static_cast<std::size_t>(0);
            }

            if (n > 1)
            {
                return len + 1 - n;
            }

            response->prepare(len);
            return len;
        },
        [weakSelf{weak_from_this()}, sensor, response](
            const boost::system::error_code& ec, std::size_t length) mutable {
            if (ec)
            {
                lg2::error("Got error reading basic query: '{ERROR_MESSAGE}'",
                           "ERROR_MESSAGE", ec.message());
                return;
            }

            if (length == 0)
            {
                lg2::error("Invalid message length: '{LEN}'", "LEN", length);
                return;
            }

            if (auto self = weakSelf.lock())
            {
                /* Deserialise the response */
                response->consume(1); /* Drop the length byte */
                std::istream is(response.get());
                std::vector<char> data(response->size());
                is.read(data.data(), response->size());

                /* Update the sensor */
                self->processResponse(sensor, data.data(), data.size());

                /* Enqueue processing of the next sensor */
                self->readAndProcessNVMeSensor();
            }
        });
}

void NVMeBasicContext::pollNVMeDevices()
{
    pollCursor = sensors.begin();

    scanTimer.expires_after(std::chrono::seconds(1));
    scanTimer.async_wait([weakSelf{weak_from_this()}](
                             const boost::system::error_code errorCode) {
        if (errorCode == boost::asio::error::operation_aborted)
        {
            return;
        }

        if (errorCode)
        {
            lg2::error("error code: '{ERROR_MESSAGE}'", "ERROR_MESSAGE",
                       errorCode.message());
            return;
        }

        if (auto self = weakSelf.lock())
        {
            self->readAndProcessNVMeSensor();
        }
    });
}

static double getTemperatureReading(int8_t reading)
{
    if (reading == static_cast<int8_t>(0x80) ||
        reading == static_cast<int8_t>(0x81))
    {
        // 0x80 = No temperature data or temperature data is more the 5 s
        // old 0x81 = Temperature sensor failure
        return std::numeric_limits<double>::quiet_NaN();
    }

    return reading;
}

void NVMeBasicContext::processResponse(std::shared_ptr<NVMeSensor>& sensor,
                                       void* msg, size_t len)
{
    if (msg == nullptr || len < 6)
    {
        sensor->incrementError();
        return;
    }

    uint8_t* messageData = static_cast<uint8_t*>(msg);

    uint8_t status = messageData[0];
    if (((status & NVME_MI_BASIC_SFLGS_DRIVE_NOT_READY) != 0) ||
        ((status & NVME_MI_BASIC_SFLGS_DRIVE_FUNCTIONAL) == 0))
    {
        sensor->markFunctional(false);
        return;
    }

    double value = getTemperatureReading(messageData[2]);
    if (!std::isfinite(value))
    {
        sensor->incrementError();
        return;
    }

    sensor->updateValue(value);
}
