#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <poll.h>
#include <unistd.h>

#include <array>
#include <file.hpp>
#include <sbe_chipOp_handler.hpp>
namespace openpower
{
namespace sbe
{
namespace internal
{

constexpr uint16_t MAGIC_CODE = 0xC0DE;
constexpr auto SBE_OPERATION_SUCCESSFUL = 0;
constexpr auto LENGTH_OF_DISTANCE_HEADER_IN_WORDS = 0x1;
constexpr auto LENGTH_OF_RESP_HEADER_IN_WORDS = 0x2;
constexpr auto DISTANCE_TO_RESP_CODE = 0x1;
constexpr auto MAX_FFDC_LEN_IN_WORDS = 5120;
constexpr auto WORD_SIZE = 4;
constexpr auto MAGIC_CODE_BITS = 16;
std::vector<sbe_word_t> writeToFifo(const char* devPath,
                                    const sbe_word_t* cmdBuffer,
                                    size_t cmdBufLen, size_t respBufLen)
{
    ssize_t len = 0;
    std::vector<sbe_word_t> response;
    std::ostringstream errMsg;

    // Open the device and obtain the file descriptor associated with it.
    FileDescriptor fileFd(devPath, (O_RDWR | O_NONBLOCK));

    // Wait for FIFO device and perform write operation
    struct pollfd poll_fd = {};
    poll_fd.fd = fileFd();
    poll_fd.events = POLLOUT | POLLERR;

    int rc = 0;
    if ((rc = poll(&poll_fd, 1, -1)) < 0)
    {
        // TODO:use elog infrastructure
        errMsg << "Waiting for FIFO device:" << devPath << "to write failed"
               << "rc=" << rc << "errno=" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }
    if (poll_fd.revents & POLLERR)
    {
        // TODO:use elog infrastructure
        errMsg << "POLLERR while waiting for writeable FIFO,errno:" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }
    auto bytesToWrite = (cmdBufLen * WORD_SIZE);
    // Perform the write operation
    len = write(fileFd(), cmdBuffer, bytesToWrite);
    if (len < 0)
    {
        // TODO:use elog infrastructure
        errMsg << "Failed to write to FIFO device:" << devPath
               << " Length "
                  "returned= "
               << len << " errno=" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }
    // Wait for FIFO device and perform read operation
    poll_fd.fd = fileFd();
    poll_fd.events = POLLIN | POLLERR;
    if ((rc = poll(&poll_fd, 1, -1) < 0))
    {
        // TODO:use elog infrastructure
        errMsg << "Waiting for FIFO device:" << devPath << "to read failed"
               << " rc=" << rc << " and errno=" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }
    if (poll_fd.revents & POLLERR)
    {
        // TODO:use elog infrastructure
        errMsg << "POLLERR while waiting for readable FIFO,errno:" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }
    // Derive the total read length which should include the FFDC, which SBE
    // returns in case of failure.
    size_t totalReadLen = respBufLen + MAX_FFDC_LEN_IN_WORDS;
    // Create a temporary buffer
    std::vector<sbe_word_t> buffer(totalReadLen);

    ssize_t bytesToRead = (totalReadLen * WORD_SIZE);
    len = read(fileFd(), buffer.data(), bytesToRead);
    if (len < 0)
    {
        // TODO:use elog infrastructure
        errMsg << "Failed to read the FIFO device:" << devPath
               << "bytes read =" << len << " errno=" << errno;
        throw std::runtime_error(errMsg.str().c_str());
    }

    // Extract the valid number of words read.
    for (auto i = 0; i < (len / WORD_SIZE); ++i)
    {
        response.push_back(be32toh(buffer[i]));
    }

    // Closing of the file descriptor will be handled when the FileDescriptor
    // object will go out of scope.
    return response;
}

void parseResponse(std::vector<sbe_word_t>& sbeDataBuf)
{
    // Number of 32-bit words obtained from the SBE
    size_t lengthObtained = sbeDataBuf.size();

    // Fetch the SBE header and SBE chiop primary and secondary status
    // Last value in the buffer will have the offset for the SBE header
    size_t distanceToStatusHeader = sbeDataBuf[sbeDataBuf.size() - 1];

    if (lengthObtained < distanceToStatusHeader)
    {
        // TODO:use elog infrastructure
        std::ostringstream errMsg;
        errMsg << "Distance to SBE status header value "
               << distanceToStatusHeader
               << " is greater then total length of "
                  "response buffer "
               << lengthObtained;
        throw std::runtime_error(errMsg.str().c_str());
    }

    // Fetch the response header contents
    auto iter = sbeDataBuf.begin();
    std::advance(iter, (lengthObtained - distanceToStatusHeader));

    // First header word will have 2 bytes of MAGIC CODE followed by
    // Command class and command type
    //|  MAGIC BYTES:0xCODE | COMMAND-CLASS | COMMAND-TYPE|
    sbe_word_t l_magicCode = (*iter >> MAGIC_CODE_BITS);

    // Fetch the primary and secondary response code
    std::advance(iter, DISTANCE_TO_RESP_CODE);
    auto l_priSecResp = *iter;

    // Validate the magic code obtained in the response
    if (l_magicCode != MAGIC_CODE)
    {
        // TODO:use elog infrastructure
        std::ostringstream errMsg;
        errMsg << "Invalid MAGIC keyword in the response header ("
               << l_magicCode << "),expected keyword " << MAGIC_CODE;
        throw std::runtime_error(errMsg.str().c_str());
    }

    // Validate the Primary and Secondary response value
    if (l_priSecResp != SBE_OPERATION_SUCCESSFUL)
    {
        // Extract the SBE FFDC and throw it to the caller
        size_t ffdcLen =
            (distanceToStatusHeader - LENGTH_OF_RESP_HEADER_IN_WORDS -
             LENGTH_OF_DISTANCE_HEADER_IN_WORDS);
        if (ffdcLen)
        {
            std::vector<sbe_word_t> ffdcData(ffdcLen);
            // Fetch the offset of FFDC data
            auto ffdcOffset = (lengthObtained - distanceToStatusHeader) +
                              LENGTH_OF_RESP_HEADER_IN_WORDS;
            std::copy_n((sbeDataBuf.begin() + ffdcOffset), ffdcLen,
                        ffdcData.begin());
        }

        // TODO:use elog infrastructure to return the SBE and Hardware procedure
        // FFDC container back to the caller.
        std::ostringstream errMsg;
        errMsg << "Chip operation failed with SBE response code:"
               << l_priSecResp
               << ".Length of FFDC data of obtained:" << ffdcLen;
        throw std::runtime_error(errMsg.str().c_str());
    }

    // In case of success, remove the response header content and send only the
    // data.Response header will be towards the end of the buffer.
    auto respLen = (lengthObtained - distanceToStatusHeader);
    iter = sbeDataBuf.begin();
    std::advance(iter, respLen);
    sbeDataBuf.erase(iter, sbeDataBuf.end());
}

} // namespace internal
} // namespace sbe
} // namespace openpower
