#include "buffer.hpp"

#include "pci_handler.hpp"

#include <fmt/format.h>

#include <boost/endian/arithmetic.hpp>
#include <boost/endian/conversion.hpp>

#include <algorithm>
#include <array>
#include <cstddef>
#include <cstdint>
#include <memory>
#include <numeric>
#include <span>
#include <vector>

namespace bios_bmc_smm_error_logger
{

BufferImpl::BufferImpl(std::unique_ptr<DataInterface> dataInterface) :
    dataInterface(std::move(dataInterface)){};

void BufferImpl::initialize(uint32_t bmcInterfaceVersion, uint16_t queueSize,
                            uint16_t ueRegionSize,
                            const std::array<uint32_t, 4>& magicNumber)
{
    const size_t memoryRegionSize = dataInterface->getMemoryRegionSize();
    const size_t proposedBufferSize =
        sizeof(struct CircularBufferHeader) + ueRegionSize + queueSize;
    if (proposedBufferSize > memoryRegionSize)
    {
        throw std::runtime_error(fmt::format(
            "[initialize] Proposed region size '{}' is bigger than the "
            "BMC's allocated MMIO region of '{}'",
            proposedBufferSize, memoryRegionSize));
    }

    // Initialize the whole buffer with 0x00
    const std::vector<uint8_t> emptyVector(proposedBufferSize, 0);
    size_t byteWritten = dataInterface->write(0, emptyVector);
    if (byteWritten != proposedBufferSize)
    {
        throw std::runtime_error(
            fmt::format("[initialize] Only erased '{}'", byteWritten));
    }

    // Create an initial buffer header and write to it
    struct CircularBufferHeader initializationHeader = {};
    initializationHeader.bmcInterfaceVersion =
        boost::endian::native_to_little(bmcInterfaceVersion);
    initializationHeader.queueSize = boost::endian::native_to_little(queueSize);
    initializationHeader.ueRegionSize =
        boost::endian::native_to_little(ueRegionSize);
    std::transform(magicNumber.begin(), magicNumber.end(),
                   initializationHeader.magicNumber.begin(),
                   [](uint32_t number) -> little_uint32_t {
                       return boost::endian::native_to_little(number);
                   });

    uint8_t* initializationHeaderPtr =
        reinterpret_cast<uint8_t*>(&initializationHeader);
    size_t initializationHeaderSize = sizeof(initializationHeader);
    byteWritten = dataInterface->write(
        0, std::span<const uint8_t>(initializationHeaderPtr,
                                    initializationHeaderPtr +
                                        initializationHeaderSize));
    if (byteWritten != initializationHeaderSize)
    {
        throw std::runtime_error(fmt::format(
            "[initialize] Only wrote '{}' bytes of the header", byteWritten));
    }
    cachedBufferHeader = initializationHeader;
}

void BufferImpl::readBufferHeader()
{
    size_t headerSize = sizeof(struct CircularBufferHeader);
    std::vector<uint8_t> bytesRead =
        dataInterface->read(/* offset */ 0, headerSize);

    if (bytesRead.size() != headerSize)
    {
        throw std::runtime_error(
            fmt::format("Buffer header read only read '{}', expected '{}'",
                        bytesRead.size(), headerSize));
    }

    cachedBufferHeader =
        *reinterpret_cast<struct CircularBufferHeader*>(bytesRead.data());
};

struct CircularBufferHeader BufferImpl::getCachedBufferHeader() const
{
    return cachedBufferHeader;
}

void BufferImpl::updateReadPtr(const uint32_t newReadPtr)
{
    constexpr uint8_t bmcReadPtrOffset =
        offsetof(struct CircularBufferHeader, bmcReadPtr);

    little_uint16_t truncatedReadPtr =
        boost::endian::native_to_little(newReadPtr & 0xffff);
    uint8_t* truncatedReadPtrPtr =
        reinterpret_cast<uint8_t*>(&truncatedReadPtr);

    size_t writtenSize = dataInterface->write(
        bmcReadPtrOffset, std::span<const uint8_t>{
                              truncatedReadPtrPtr,
                              truncatedReadPtrPtr + sizeof(little_uint16_t)});
    if (writtenSize != sizeof(little_uint16_t))
    {
        throw std::runtime_error(fmt::format(
            "[updateReadPtr] Wrote '{}' bytes, instead of expected '{}'",
            writtenSize, sizeof(little_uint16_t)));
    }
    cachedBufferHeader.bmcReadPtr = truncatedReadPtr;
}

size_t BufferImpl::getQueueOffset()
{
    return sizeof(struct CircularBufferHeader) +
           boost::endian::little_to_native(cachedBufferHeader.ueRegionSize);
}

std::vector<uint8_t>
    BufferImpl::wraparoundRead(const uint32_t offset, const uint32_t length,
                               const uint32_t additionalBoundaryCheck)
{
    const size_t queueSize =
        boost::endian::little_to_native(cachedBufferHeader.queueSize);

    if (length + additionalBoundaryCheck > queueSize)
    {
        throw std::runtime_error(fmt::format(
            "[wraparoundRead] length '{}' + additionalBoundaryCheck '{}' "
            "was bigger than queueSize '{}'",
            length, additionalBoundaryCheck, queueSize));
    }

    // Do a first read up to the end of the buffer (dataInerface->read should
    // only read up to the end of the buffer)
    std::vector<uint8_t> bytesRead = dataInterface->read(offset, length);
    size_t updatedReadOffset = offset + bytesRead.size();
    size_t bytesRemaining = length - bytesRead.size();

    // If there are any more bytes to be read beyond the buffer, wrap around and
    // read from the beginning of the buffer (offset by the queueOffset)
    size_t queueOffset = getQueueOffset();
    if (bytesRemaining > 0)
    {
        std::vector<uint8_t> wrappedBytesRead =
            dataInterface->read(queueOffset, bytesRemaining);
        bytesRemaining -= wrappedBytesRead.size();
        if (bytesRemaining != 0)
        {
            throw std::runtime_error(fmt::format(
                "[wraparoundRead] Buffer wrapped around but was not able to read "
                "all of the requested info. Bytes remaining to read '{}' of '{}'",
                bytesRemaining, length));
        }
        bytesRead.insert(bytesRead.end(), wrappedBytesRead.begin(),
                         wrappedBytesRead.end());
        updatedReadOffset = wrappedBytesRead.size();
    }
    updateReadPtr(updatedReadOffset);

    return bytesRead;
}

struct QueueEntryHeader BufferImpl::readEntryHeader(size_t offset)
{
    size_t headerSize = sizeof(struct QueueEntryHeader);
    // wraparonudRead will throw if it did not read all the bytes, let it
    // propagate up the stack
    std::vector<uint8_t> bytesRead = wraparoundRead(offset, headerSize);

    return *reinterpret_cast<struct QueueEntryHeader*>(bytesRead.data());
}

EntryPair BufferImpl::readEntry(size_t offset)
{
    struct QueueEntryHeader entryHeader = readEntryHeader(offset);

    size_t entrySize = entryHeader.entrySize;

    // wraparonudRead may throw if entrySize was bigger than the buffer or if it
    // was not able to read all the bytes, let it propagate up the stack
    // - Use additionalBoundaryCheck parameter to add QueueEntryHeader size to
    //   boundary condition calculation
    std::vector<uint8_t> entry =
        wraparoundRead(offset + sizeof(struct QueueEntryHeader), entrySize,
                       sizeof(struct QueueEntryHeader));

    // Calculate the checksum
    uint8_t* entryHeaderPtr = reinterpret_cast<uint8_t*>(&entryHeader);
    uint8_t checksum = std::accumulate(
        entryHeaderPtr, entryHeaderPtr + sizeof(struct QueueEntryHeader), 0);
    checksum = std::accumulate(std::begin(entry), std::end(entry), checksum);
    if (checksum != 0)
    {
        throw std::runtime_error(fmt::format(
            "[readEntry] Checksum was '{}', expected '0'", checksum));
    }

    return {entryHeader, entry};
}

} // namespace bios_bmc_smm_error_logger
