#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);
        });
}

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);
}

Response Handler::handleMultipartReceive(
    pldm_tid_t tid, const pldm_msg* request, size_t reqMsgLen)
{
    return dfRead(tid, request, reqMsgLen);
}

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