#include "file_io.hpp"

#include "file_io_type_bios_version.hpp"
#include "file_io_type_event_log.hpp"
#include "file_io_type_http_boot.hpp"
#include "file_io_type_post_code.hpp"
#include "file_io_type_power_control.hpp"

#include <libpldm/oem/meta/file_io.h>

namespace pldm::responder::oem_meta
{

std::unique_ptr<FileHandler> FileIOHandler::getHandlerByType(
    [[maybe_unused]] pldm_tid_t messageTid, FileIOType fileIOType)
{
    switch (fileIOType)
    {
        case FileIOType::POST_CODE:
            return std::make_unique<PostCodeHandler>(messageTid);
        case FileIOType::BIOS_VERSION:
            return std::make_unique<BIOSVersionHandler>(messageTid,
                                                        dBusHandler);
        case FileIOType::POWER_CONTROL:
            return std::make_unique<PowerControlHandler>(messageTid,
                                                         dBusHandler);
        case FileIOType::HTTP_BOOT:
            return std::make_unique<HttpBootHandler>();
        case FileIOType::EVENT_LOG:
            return std::make_unique<EventLogHandler>(messageTid);
        default:
            error("Get invalid file io type {FILEIOTYPE}", "FILEIOTYPE",
                  fileIOType);
            break;
    }
    return nullptr;
}

Response FileIOHandler::writeFileIO(pldm_tid_t tid, const pldm_msg* request,
                                    size_t payloadLength)
{
    static constexpr uint8_t decodeDataMaxLength = 240;
    constexpr uint8_t decodereqlen =
        PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH + decodeDataMaxLength;
    alignas(struct pldm_oem_meta_file_io_write_req) unsigned char
        reqbuf[decodereqlen];
    auto request_msg = new (reqbuf) pldm_oem_meta_file_io_write_req;
    auto request_data = static_cast<uint8_t*>(
        pldm_oem_meta_file_io_write_req_data(request_msg));

    int rc = decode_oem_meta_file_io_write_req(request, payloadLength,
                                               request_msg, decodereqlen);

    if (rc != 0)
    {
        error("Failed to decode OEM Meta write file IO request");
        return ccOnlyResponse(request, rc);
    }

    auto handler =
        getHandlerByType(tid, static_cast<FileIOType>(request_msg->handle));
    if (!handler)
    {
        return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
    }

    auto data = std::span(request_data, request_msg->length);

    rc = handler->write(data);

    return ccOnlyResponse(request, rc);
}

Response FileIOHandler::readFileIO(pldm_tid_t tid, const pldm_msg* request,
                                   size_t payloadLength)
{
    int rc = 0;
    struct pldm_oem_meta_file_io_read_req request_msg = {};
    request_msg.version = sizeof(struct pldm_oem_meta_file_io_read_req);

    rc = decode_oem_meta_file_io_read_req(request, payloadLength, &request_msg);

    if (rc != 0)
    {
        error("Failed to decode OEM Meta read file IO request");
        return ccOnlyResponse(request, rc);
    }

    auto handler =
        getHandlerByType(tid, static_cast<FileIOType>(request_msg.handle));

    if (!handler)
    {
        return ccOnlyResponse(request, PLDM_ERROR_UNSUPPORTED_PLDM_CMD);
    }

    size_t encoderesplen = PLDM_OEM_META_FILE_IO_READ_RESP_MIN_SIZE;
    if (request_msg.option == PLDM_OEM_META_FILE_IO_READ_ATTR)
    {
        encoderesplen += PLDM_OEM_META_FILE_IO_READ_ATTR_INFO_LENGTH;
    }
    else
    {
        encoderesplen += PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH;
    }

    std::vector<uint8_t> respbuf(
        sizeof(struct pldm_oem_meta_file_io_read_resp) + request_msg.length);
    auto* response_msg = new (respbuf.data()) pldm_oem_meta_file_io_read_resp;

    response_msg->version = sizeof(struct pldm_oem_meta_file_io_read_resp);
    response_msg->handle = request_msg.handle;
    response_msg->option = request_msg.option;
    response_msg->length = request_msg.length;

    if (response_msg->option != PLDM_OEM_META_FILE_IO_READ_ATTR)
    {
        response_msg->info.data.transferFlag =
            request_msg.info.data.transferFlag;
        response_msg->info.data.offset = request_msg.info.data.offset;
    }

    rc = handler->read(response_msg);

    if (rc != PLDM_SUCCESS)
    {
        return ccOnlyResponse(request, rc);
    }

    response_msg->completion_code = PLDM_SUCCESS;
    encoderesplen += response_msg->length;

    Response response(sizeof(pldm_msg_hdr) + encoderesplen, 0);
    auto responseMsg = new (response.data()) pldm_msg;

    rc = encode_oem_meta_file_io_read_resp(
        request->hdr.instance_id, response_msg,
        sizeof(struct pldm_oem_meta_file_io_read_resp) + response_msg->length,
        responseMsg, encoderesplen);

    if (rc != 0)
    {
        return ccOnlyResponse(request, rc);
    }

    return response;
}

} // namespace pldm::responder::oem_meta
