#include "file_transfer.hpp"

#include <libpldm/base.h>

#include <phosphor-logging/lg2.hpp>

#include <fstream>
#include <optional>
#include <vector>

PHOSPHOR_LOG2_USING;

namespace pldm
{
namespace responder
{
namespace file_transfer
{

int fileRead(FILE* fp, uint32_t fileSize, uint32_t offset, uint32_t readSize,
             uint8_t* dataPtr)
{
    if (!fp)
    {
        error("Error: fileRead received a NULL FILE pointer.");
        return -1;
    }

    if (!dataPtr)
    {
        error("Error: fileRead received a NULL dataPtr buffer.");
        return -1;
    }

    if (readSize == 0)
    {
        return 0;
    }

    if (offset >= fileSize)
    {
        error("Error: Start offset '{OFFSET}' is beyond file size '{FSIZE}'.",
              "OFFSET", offset, "FSIZE", fileSize);
        return -1;
    }

    if (readSize > fileSize)
    {
        error("Error: readSize '{READ_SIZE}' is beyond file size '{FSIZE}'.",
              "READ_SIZE", readSize, "FSIZE", fileSize);
        return -1;
    }

    if (offset > fileSize - readSize)
    {
        error(
            "Error: Read would go beyond file size. Offset '{OFFSET}', readSize '{READ_SIZE}', fileSize '{FSIZE}'.",
            "OFFSET", offset, "READ_SIZE", readSize, "FSIZE", fileSize);
        return -1;
    }

    if (fseek(fp, offset, SEEK_SET) != 0)
    {
        error("Error: fseek failed");
        return -1;
    }

    size_t bytes_read = fread(dataPtr, 1, readSize, fp);
    if (bytes_read != readSize)
    {
        if (feof(fp))
        {
            error("Error: Unexpected end of file reached.");
        }
        else if (ferror(fp))
        {
            error("Error: fread failed");
        }
        else
        {
            error("Error: Unknown fread error.");
        }
        return -1;
    }

    return 0;
}

Handler::Handler(responder::base::Handler* baseHandler,
                 responder::platform::Handler* platformHandler) :
    baseHandler(baseHandler), platformHandler(platformHandler),
    nextFileDescriptor(0)
{
    // Register command handlers. The "handlers" come from CmdHandler class.
    handlers.emplace(
        PLDM_FILE_CMD_DF_OPEN,
        [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
            return this->dfOpen(request, payloadLength);
        });

    handlers.emplace(
        PLDM_FILE_CMD_DF_CLOSE,
        [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
            return this->dfClose(request, payloadLength);
        });

    handlers.emplace(
        PLDM_FILE_CMD_DF_READ,
        [this](pldm_tid_t tid, const pldm_msg* request, size_t payloadLength) {
            return this->dfRead(tid, request, payloadLength);
        });
}

std::optional<uint16_t> Handler::getFreeFileDescriptor(uint16_t fileIdentifier)
{
    uint16_t startValue = this->nextFileDescriptor;

    // Find a free descriptor value.
    // TODO: In case a device do not release file descriptors by calling
    // dfClose, we will need a mechanism to free unused file descriptors
    while (this->fileDescriptors.contains(this->nextFileDescriptor))
    {
        ++(this->nextFileDescriptor);
        if (this->nextFileDescriptor == startValue)
        {
            return std::nullopt;
        }
    }

    // TODO: Also track client TID with the file descriptor for better request
    // filtering.
    this->fileDescriptors.emplace(
        this->nextFileDescriptor,
        FileDescriptor{.fp = nullptr,
                       .fileSize = 0,
                       .startingOffset = 0,
                       .sectionLength = 0,
                       .prevChecksum = 0,
                       .fileIdentifier = fileIdentifier});
    return this->nextFileDescriptor;
}

void Handler::removeFileDescriptor(uint16_t fileDescriptor)
{
    fileDescriptors.erase(fileDescriptor);
}

Response Handler::dfOpen(const pldm_msg* request, size_t payloadLength)
{
    pldm_file_df_open_req decodedReq;
    int rc = decode_pldm_file_df_open_req(request, payloadLength, &decodedReq);
    if (rc != 0)
    {
        error("Failed to decode DfOpen request. Err: '{ERROR}'", "ERROR", rc);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    uint16_t file_identifier = decodedReq.file_identifier;
    std::optional<uint16_t> fdOrRet = getFreeFileDescriptor(file_identifier);
    if (!fdOrRet.has_value())
    {
        error(
            "No free file descriptors available for FileIdentifier: '{FILE_ID}'",
            "FILE_ID", file_identifier);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_UNABLE_TO_OPEN_FILE);
    }

    FILE* fp = nullptr;
    uint32_t fileSize;

    // TODO: We might need a mechanism to cleanup the unsued file pointers
    // returned here if dfClose is not called on this. One way to do that would
    // be to update a time value in struct FileDescriptor based on the last time
    // a file transfer operation was performed on it.
    int ret = platformHandler->getFilePointer(file_identifier, &fp, &fileSize);
    if (ret != 0)
    {
        error("Requested FileIdentifier: '{FILE_ID}' not found in PDR",
              "FILE_ID", file_identifier);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_IDENTIFIER);
    }

    // Save the open file information
    FileDescriptor& fileDescriptor = fileDescriptors[fdOrRet.value()];
    fileDescriptor.fp = fp;
    fileDescriptor.fileSize = fileSize;

    size_t respPayloadLength = PLDM_DF_OPEN_RESP_BYTES;
    Response response(sizeof(pldm_msg_hdr) + respPayloadLength, 0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    pldm_file_df_open_resp resp;
    resp.completion_code = PLDM_SUCCESS;
    resp.file_descriptor = fdOrRet.value();

    rc = encode_pldm_file_df_open_resp(request->hdr.instance_id, &resp,
                                       responsePtr, &respPayloadLength);
    if (rc != 0)
    {
        removeFileDescriptor(fdOrRet.value());
        fclose(fp);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    return response;
}

Response Handler::dfClose(const pldm_msg* request, size_t payloadLength)
{
    pldm_file_df_close_req decodedReq;
    int rc = decode_pldm_file_df_close_req(request, payloadLength, &decodedReq);
    if (rc != 0)
    {
        error("Failed to decode DfClose request. Err: '{ERROR}'", "ERROR", rc);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    uint16_t file_descriptor = decodedReq.file_descriptor;

    auto it = fileDescriptors.find(file_descriptor);
    if (it == fileDescriptors.end())
    {
        error("Requested FileDescriptor: '{FILE_DES}' is not valid", "FILE_DES",
              file_descriptor);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_DESCRIPTOR);
    }

    size_t respPayloadLength = PLDM_DF_CLOSE_RESP_BYTES;
    Response response(sizeof(pldm_msg_hdr) + respPayloadLength, 0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    pldm_file_df_close_resp resp;
    resp.completion_code = PLDM_SUCCESS;

    rc = encode_pldm_file_df_close_resp(request->hdr.instance_id, &resp,
                                        responsePtr, &respPayloadLength);
    if (rc != 0)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    // If there is any other failure before this, we should not clean the
    // resources and wait for another dfClose.
    fclose(it->second.fp);
    removeFileDescriptor(file_descriptor);

    return response;
}

uint32_t Handler::getDataLengthBytesAndTransferFlag(
    const FileDescriptor& fileDescriptor, uint32_t currOffset,
    uint16_t multipartSize, uint8_t* transferFlag)
{
    // Verify that the current offset is greater than the starting offset of the
    // data sequence.
    if (currOffset < fileDescriptor.startingOffset)
    {
        error(
            "currOffset: '{CUR_OFFSET}' cannot be smaller than starting_offset: '{ST_OFFSET}'",
            "CUR_OFFSET", currOffset, "ST_OFFSET",
            fileDescriptor.startingOffset);
        return 0;
    }

    // Calculate already sent data
    uint32_t sentData = currOffset - fileDescriptor.startingOffset;

    if (sentData > fileDescriptor.sectionLength)
    {
        error(
            "sentData: '{SENT_DATA}' cannot be larger than section_length: '{SECT_LEN}'",
            "SENT_DATA", sentData, "SECT_LEN", fileDescriptor.sectionLength);
        return 0;
    }

    uint32_t remaingData = fileDescriptor.sectionLength - sentData;
    if (remaingData == 0)
    {
        error(
            "Ramaining data cannot be 0. Client might be requesting data beyond initially negotiated section size");
        return 0;
    }

    // Includes the size of the 32bit checksum
    uint32_t nonDataLength =
        sizeof(pldm_msg_hdr) + PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES +
        sizeof(uint32_t);
    uint32_t lenForData = multipartSize - nonDataLength;

    // Derive the response transfer flag
    if (sentData == 0)
    {
        *transferFlag =
            (lenForData < remaingData) ? PLDM_START : PLDM_START_AND_END;
    }
    else
    {
        *transferFlag = (lenForData < remaingData) ? PLDM_MIDDLE : PLDM_END;
    }

    return std::min(lenForData, remaingData);
}

uint32_t Handler::getNextOffset(uint32_t currOffset, uint32_t dataLengthBytes)
{
    return currOffset + dataLengthBytes;
}

Response Handler::createReadResponse(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    FileDescriptor& fileDescriptor, uint32_t currentTransferHandle,
    uint8_t transferFlag, uint32_t nextTransferHandle, uint32_t dataLengthBytes)
{
    // data_length_bytes shouldn't be 0 unless this is ACK response
    if ((transferFlag != PLDM_ACKNOWLEDGE_COMPLETION) && (dataLengthBytes == 0))
    {
        error("data_length_bytes cannot be 0 unless this is ACK response");
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    // Response payload length includes the checksum if there is data
    size_t respPayloadLength =
        PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES + dataLengthBytes;
    if (dataLengthBytes > 0)
    {
        respPayloadLength += sizeof(uint32_t);
    }

    Response response(sizeof(pldm_msg_hdr) + respPayloadLength, 0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    struct pldm_base_multipart_receive_resp resp;
    resp.completion_code = PLDM_SUCCESS;
    resp.transfer_flag = transferFlag;
    resp.next_transfer_handle = nextTransferHandle;
    resp.data.length = dataLengthBytes;

    uint8_t* dataPtr = nullptr;
    uint32_t checksum = 0;

    // Read the file data and calculate the checksum if dataLengthBytes is non
    // zero
    if (dataLengthBytes > 0)
    {
        // Point data.ptr to the start of the data section
        dataPtr = responsePtr->payload +
                  PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES;
        int ret = fileRead(fileDescriptor.fp, fileDescriptor.fileSize,
                           currentTransferHandle, dataLengthBytes, dataPtr);
        if (ret != 0)
        {
            return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
        }

        // Calculate checksum
        if ((transferFlag == PLDM_START) ||
            (transferFlag == PLDM_START_AND_END))
        {
            checksum = pldm_edac_crc32(dataPtr, dataLengthBytes);
        }
        else
        {
            checksum = pldm_edac_crc32_extend(dataPtr, dataLengthBytes,
                                              fileDescriptor.prevChecksum);
        }
    }

    resp.data.ptr = dataPtr;

    // If this is a response for a PLDM_XFER_CURRENT_PART, checksum is the same
    // as the previous one.
    if (decodedReq.transfer_opflag == PLDM_XFER_CURRENT_PART)
    {
        checksum = fileDescriptor.prevChecksum;
    }

    int ret = encode_base_multipart_receive_resp(
        request->hdr.instance_id, &resp, checksum, responsePtr,
        &respPayloadLength);
    if (ret != 0)
    {
        error("Multipart receive resp encoding failed for dfRead: {ERROR}",
              "ERROR", ret);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    fileDescriptor.prevChecksum = checksum;
    return response;
}

Response Handler::dfReadTransferFirstPart(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    uint16_t multipartSize, FileDescriptor& fileDescriptor)
{
    // For the first part, transfer handle should be 0
    if (decodedReq.transfer_handle != 0)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Verify that the offset is within file size
    if (decodedReq.section_offset >= fileDescriptor.fileSize)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Verify that the offset + read length is within file size
    if (decodedReq.section_length >
        fileDescriptor.fileSize - decodedReq.section_offset)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    fileDescriptor.startingOffset = decodedReq.section_offset;
    fileDescriptor.sectionLength = decodedReq.section_length;

    // If the requested section length is 0, the requester doesn't know the
    // size. So the remainder of the complete file will be transmitted.
    if (decodedReq.section_length == 0)
    {
        fileDescriptor.sectionLength =
            fileDescriptor.fileSize - decodedReq.section_offset;
    }

    // Get the length of the data bytes we need to transfer in this packet and
    // the corresponding transfer flag.
    uint8_t transfer_flag;
    uint32_t data_length_bytes = getDataLengthBytesAndTransferFlag(
        fileDescriptor, fileDescriptor.startingOffset, multipartSize,
        &transfer_flag);
    if (data_length_bytes == 0)
    {
        // This can happen if the client is requesting data beyond initially
        // negotiated values.
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Transfer handle is used as the offset to the file. Get the next transfer
    // handle if are more future packets in this sequence.
    uint32_t next_transfer_handle = 0;
    if (transfer_flag == PLDM_START)
    {
        next_transfer_handle =
            getNextOffset(fileDescriptor.startingOffset, data_length_bytes);
    }

    return createReadResponse(request, decodedReq, fileDescriptor,
                              fileDescriptor.startingOffset, transfer_flag,
                              next_transfer_handle, data_length_bytes);
}

Response Handler::dfReadTransferCurrentOrNextPart(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    uint16_t multipartSize, FileDescriptor& fileDescriptor)
{
    // Validate transfer flag. This doesn't strictly check the transfer flag
    // with an expected value. Instead veryfying that it is within valid range.
    if (decodedReq.transfer_handle < fileDescriptor.startingOffset)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Validate that the transfer_handle is within requested data range.
    if (decodedReq.transfer_handle - fileDescriptor.startingOffset >=
        fileDescriptor.sectionLength)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Get the length of the data bytes we need to transfer in this packet and
    // the corresponding transfer flag.
    uint8_t transfer_flag;
    uint32_t data_length_bytes = getDataLengthBytesAndTransferFlag(
        fileDescriptor, decodedReq.transfer_handle, multipartSize,
        &transfer_flag);
    if (data_length_bytes == 0)
    {
        // This can happen if the client is requesting data beyond initially
        // negotiated values.
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Transfer handle is used as the offset to the file. Get the next transfer
    // handle if are more future packets in this sequence.
    uint32_t next_transfer_handle = 0;
    if ((transfer_flag == PLDM_START) || (transfer_flag == PLDM_MIDDLE))
    {
        next_transfer_handle =
            getNextOffset(decodedReq.transfer_handle, data_length_bytes);
    }

    return createReadResponse(request, decodedReq, fileDescriptor,
                              decodedReq.transfer_handle, transfer_flag,
                              next_transfer_handle, data_length_bytes);
}

Response Handler::dfReadTransferCompleteOrAbort(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    uint16_t multipartSize, FileDescriptor& fileDescriptor)
{
    // Check whether the requester wants to start a new connection
    if (decodedReq.section_length > 0 || decodedReq.section_offset > 0)
    {
        return dfReadTransferFirstPart(request, decodedReq, multipartSize,
                                       fileDescriptor);
    }
    return createReadResponse(
        request, decodedReq, fileDescriptor, /*current_transfer_handle=*/0,
        /*transfer_flag*/ PLDM_ACKNOWLEDGE_COMPLETION,
        /*next_transfer_handle*/ 0, /*data_length_bytes*/ 0);
}

Response Handler::dfRead(pldm_tid_t tid, const pldm_msg* request,
                         size_t payloadLength)
{
    uint8_t pldmType;
    uint8_t transferOpflag;
    uint32_t transferCtx;
    uint32_t transferHandle;
    uint32_t sectionOffset;
    uint32_t sectionLength;

    int rc = decode_multipart_receive_req(
        request, payloadLength, &pldmType, &transferOpflag, &transferCtx,
        &transferHandle, &sectionOffset, &sectionLength);
    if (rc != 0)
    {
        error("Failed to decode DfRead request. Err: '{ERROR}'", "ERROR", rc);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    pldm_base_multipart_receive_req decodedReq;
    decodedReq.pldm_type = pldmType;
    decodedReq.transfer_opflag = transferOpflag;
    decodedReq.transfer_ctx = transferCtx;
    decodedReq.transfer_handle = transferHandle;
    decodedReq.section_offset = sectionOffset;
    decodedReq.section_length = sectionLength;

    uint32_t file_descriptor = transferCtx;
    auto it = fileDescriptors.find(file_descriptor);
    if (it == fileDescriptors.end())
    {
        error("Requested FileDescriptor: '{FILE_DES}' is not valid", "FILE_DES",
              file_descriptor);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_DESCRIPTOR);
    }

    uint16_t multipartSize = baseHandler->getNegotiatedPartSize(tid, PLDM_FILE);

    switch (transferOpflag)
    {
        case PLDM_XFER_FIRST_PART:
            return dfReadTransferFirstPart(request, decodedReq, multipartSize,
                                           it->second);
        case PLDM_XFER_NEXT_PART:
            return dfReadTransferCurrentOrNextPart(request, decodedReq,
                                                   multipartSize, it->second);
        case PLDM_XFER_ABORT:
            return dfReadTransferCompleteOrAbort(request, decodedReq,
                                                 multipartSize, it->second);
        case PLDM_XFER_COMPLETE:
            return dfReadTransferCompleteOrAbort(request, decodedReq,
                                                 multipartSize, it->second);
        case PLDM_XFER_CURRENT_PART:
            return dfReadTransferCurrentOrNextPart(request, decodedReq,
                                                   multipartSize, it->second);
        default:
            break;
    }

    return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
}

} // namespace file_transfer
} // namespace responder
} // namespace pldm
