#include "file_transfer.hpp"

#include <libpldm/base.h>
#include <libpldm/edac.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 bytesRead = fread(dataPtr, 1, readSize, fp);
    if (bytesRead != 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 tid, const pldm_msg* request, size_t payloadLength) {
            return this->dfOpen(tid, request, payloadLength);
        });

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

std::optional<uint16_t> Handler::getFreeFileDescriptor()
{
    // Audit and purge logical descriptors that have timed out in platform
    for (auto it = fileDescriptors.cbegin(); it != fileDescriptors.cend();)
    {
        if (!platformHandler->isSnapshotValid(it->second.tid,
                                              it->second.fileIdentifier))
        {
            info("Purging stale logical file descriptor {FD} for TID {TID}",
                 "FD", it->first, "TID", it->second.tid);
            it = fileDescriptors.erase(it);
            continue;
        }
        ++it;
    }

    uint16_t startValue = this->nextFileDescriptor;

    // Find a free descriptor value.
    while (this->fileDescriptors.contains(this->nextFileDescriptor))
    {
        ++(this->nextFileDescriptor);
        if (this->nextFileDescriptor == startValue)
        {
            return std::nullopt;
        }
    }

    return this->nextFileDescriptor;
}

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

Response Handler::dfOpen(pldm_tid_t tid, 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 fileIdentifier = decodedReq.file_identifier;
    std::optional<uint16_t> fdOrRet = getFreeFileDescriptor();
    if (!fdOrRet.has_value())
    {
        error(
            "No free file descriptors available for tid:`{TID}` FileIdentifier: '{FILE_ID}'",
            "TID", tid, "FILE_ID", fileIdentifier);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_UNABLE_TO_OPEN_FILE);
    }

    FILE* fp = nullptr;
    uint32_t fileSize;

    int ret = platformHandler->transferSnapshotFile(fileIdentifier, tid, &fp,
                                                    &fileSize);
    if (ret != 0)
    {
        error("Failed to get snapshot for TID {TID} FileIdentifier: {FILE_ID}",
              "TID", tid, "FILE_ID", fileIdentifier);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_IDENTIFIER);
    }

    fileDescriptors.emplace(
        fdOrRet.value(),
        FileDescriptor{.fp = fp,
                       .tid = tid,
                       .index = fdOrRet.value(),
                       .fileSize = fileSize,
                       .startingOffset = 0,
                       .sectionLength = 0,
                       .sentLength = 0,
                       .prevChecksum = 0,
                       .fileIdentifier = fileIdentifier});

    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());
        // FILE* fp is owned by platformHandler, so don't close here
        error("Failed to encode DfOpen response. Err: '{ERROR}'", "ERROR", rc);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    info("DfOpen received. tid:{TID} fi:{FI} fd:{FD}", "TID", tid, "FI",
         fileIdentifier, "FD", fdOrRet.value());

    return response;
}

Response Handler::dfClose(pldm_tid_t tid, 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 fileDescriptor = decodedReq.file_descriptor;

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

    if (it->second.tid != tid)
    {
        error(
            "Requested FileDescriptor: '{FILE_DES}' is not owned by TID: '{TID}'",
            "FILE_DES", fileDescriptor, "TID", tid);
        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)
    {
        error("Failed to encode DfClose response. Err: '{ERROR}'", "ERROR", rc);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    info("DfClose received. tid:{TID} fd:{FD} sentSize:{SIZE}", "TID", tid,
         "FD", fileDescriptor, "SIZE", it->second.sentLength);

    // FILE* fp is owned by platformHandler. So don't close here.
    removeFileDescriptor(fileDescriptor);

    return response;
}

uint32_t Handler::getDataLengthBytesAndTransferFlag(
    const FileDescriptor& fileDescriptor, uint32_t sentData,
    uint16_t multipartSize, uint8_t* transferFlag)
{
    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 currentOffset,
    uint8_t transferFlag, uint32_t nextTransferHandle, uint32_t dataLengthBytes)
{
    // dataLengthBytes shouldn't be 0 unless this is ACK response
    if ((transferFlag != PLDM_ACKNOWLEDGE_COMPLETION) && (dataLengthBytes == 0))
    {
        error("dataLengthBytes 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,
                           currentOffset, 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.sentLength is updated for debugging purposes.
    if (transferFlag == PLDM_START)
    {
        fileDescriptor.sentLength = dataLengthBytes;
        info("Transferring DfRead first part. tid:{TID} fd:{FD}", "TID",
             fileDescriptor.tid, "FD", fileDescriptor.index);
    }
    else if (transferFlag == PLDM_MIDDLE)
    {
        // PLDM_MIDDLE indicates that there is more data to be sent. So sent
        // data len is the nextTransferHandle.
        fileDescriptor.sentLength = nextTransferHandle;
    }
    else if (transferFlag == PLDM_START_AND_END)
    {
        // PLDM_START_AND_END indicates that all the data is sent.
        fileDescriptor.sentLength = fileDescriptor.sectionLength;
        info("Transferring DfRead first and last part. tid:{TID} fd:{FD}",
             "TID", fileDescriptor.tid, "FD", fileDescriptor.index);
    }
    else if (transferFlag == PLDM_END)
    {
        // PLDM_END indicates that all the data is sent.
        fileDescriptor.sentLength = fileDescriptor.sectionLength;
        info("Transferring DfRead last part. tid:{TID} fd:{FD}", "TID",
             fileDescriptor.tid, "FD", fileDescriptor.index);
    }

    fileDescriptor.prevChecksum = checksum;
    return response;
}

Response Handler::dfReadTransferFirstPart(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    uint16_t multipartSize, FileDescriptor& fileDescriptor)
{
    info(
        "DfRead first part request received. tid:{TID} fd:{FD} offset:{OFFSET} sectionLength:{SECT_LEN}",
        "TID", fileDescriptor.tid, "FD", fileDescriptor.index, "OFFSET",
        decodedReq.section_offset, "SECT_LEN", decodedReq.section_length);

    // 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 transferFlag;
    uint32_t dataLengthBytes = getDataLengthBytesAndTransferFlag(
        fileDescriptor, /*sentData=*/0, multipartSize, &transferFlag);
    if (dataLengthBytes == 0)
    {
        // This can happen if the client is requesting data beyond initially
        // negotiated values.
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // If there are more future packets, then we need to derive a next transfer
    // handle. (nextTransferHandle + fileDescriptor.starting_offset) will be
    // used as the offset to the file.
    uint32_t nextTransferHandle = 0;
    if (transferFlag == PLDM_START)
    {
        nextTransferHandle = dataLengthBytes;
    }

    return createReadResponse(request, decodedReq, fileDescriptor,
                              fileDescriptor.startingOffset, transferFlag,
                              nextTransferHandle, dataLengthBytes);
}

Response Handler::dfReadTransferCurrentOrNextPart(
    const pldm_msg* request, const pldm_base_multipart_receive_req& decodedReq,
    uint16_t multipartSize, FileDescriptor& fileDescriptor)
{
    // Sanity check for transfer_handle. It represent the already sent data
    if (decodedReq.transfer_handle >= 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 transferFlag;
    uint32_t dataLengthBytes = getDataLengthBytesAndTransferFlag(
        fileDescriptor, decodedReq.transfer_handle, multipartSize,
        &transferFlag);
    if (dataLengthBytes == 0)
    {
        // This can happen if the client is requesting data beyond initially
        // negotiated values.
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // If there are more future packets, then we need to derive a next transfer
    // handle. (nextTransferHandle + fileDescriptor.starting_offset) will be
    // used as the offset to the file.
    uint32_t nextTransferHandle = 0;
    if ((transferFlag == PLDM_START) || (transferFlag == PLDM_MIDDLE))
    {
        nextTransferHandle = decodedReq.transfer_handle + dataLengthBytes;
    }

    // Derive the current offset we need to read
    uint32_t currOffset =
        fileDescriptor.startingOffset + decodedReq.transfer_handle;

    return createReadResponse(request, decodedReq, fileDescriptor, currOffset,
                              transferFlag, nextTransferHandle,
                              dataLengthBytes);
}

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, /*currentOffset=*/0,
        /*transferFlag*/ PLDM_ACKNOWLEDGE_COMPLETION,
        /*nextTransferHandle*/ 0, /*dataLengthBytes*/ 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 fileDescriptor = transferCtx;
    auto it = fileDescriptors.find(fileDescriptor);
    if (it == fileDescriptors.end())
    {
        error("Requested FileDescriptor: '{FILE_DES}' is not valid", "FILE_DES",
              fileDescriptor);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_DESCRIPTOR);
    }

    if (it->second.tid != tid)
    {
        error(
            "Requested FileDescriptor: '{FILE_DES}' is not owned by TID: '{TID}'",
            "FILE_DES", fileDescriptor, "TID", tid);
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_FILE_CC_INVALID_FILE_DESCRIPTOR);
    }

    if (!platformHandler->isSnapshotValid(it->second.tid,
                                          it->second.fileIdentifier))
    {
        error(
            "Snapshot for FileDescriptor '{FILE_DES}' has timed out in platform",
            "FILE_DES", fileDescriptor);
        removeFileDescriptor(fileDescriptor);
        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
