#include "base.hpp"

#include "common/utils.hpp"
#include "libpldmresponder/pdr.hpp"

#include <libpldm/base.h>
#include <libpldm/bios.h>
#include <libpldm/file.h>
#include <libpldm/fru.h>
#include <libpldm/platform.h>

#include <phosphor-logging/lg2.hpp>

#include <algorithm>
#include <array>
#include <bit>
#include <cstring>
#include <map>
#include <stdexcept>
#include <vector>

#ifdef OEM_IBM
#include <libpldm/oem/ibm/file_io.h>
#include <libpldm/oem/ibm/host.h>
#endif

PHOSPHOR_LOG2_USING;

namespace pldm
{
using Type = uint8_t;

namespace responder
{
using Cmd = std::vector<uint8_t>;

static const std::map<Type, Cmd> capabilities{
    {PLDM_BASE,
     {PLDM_GET_TID, PLDM_GET_PLDM_VERSION, PLDM_GET_PLDM_TYPES,
      PLDM_GET_PLDM_COMMANDS, PLDM_NEGOTIATE_TRANSFER_PARAMETERS,
      PLDM_MULTIPART_RECEIVE}},
    {PLDM_PLATFORM,
     {PLDM_GET_PDR, PLDM_SET_STATE_EFFECTER_STATES, PLDM_SET_EVENT_RECEIVER,
      PLDM_GET_SENSOR_READING, PLDM_GET_STATE_SENSOR_READINGS,
      PLDM_SET_NUMERIC_EFFECTER_VALUE, PLDM_GET_NUMERIC_EFFECTER_VALUE,
      PLDM_PLATFORM_EVENT_MESSAGE}},
    {PLDM_BIOS,
     {PLDM_GET_DATE_TIME, PLDM_SET_DATE_TIME, PLDM_GET_BIOS_TABLE,
      PLDM_GET_BIOS_ATTRIBUTE_CURRENT_VALUE_BY_HANDLE,
      PLDM_SET_BIOS_ATTRIBUTE_CURRENT_VALUE, PLDM_SET_BIOS_TABLE}},
    {PLDM_FRU,
     {PLDM_GET_FRU_RECORD_TABLE_METADATA, PLDM_GET_FRU_RECORD_TABLE,
      PLDM_GET_FRU_RECORD_BY_OPTION}},
    {PLDM_FILE,
     {PLDM_FILE_CMD_DF_OPEN, PLDM_FILE_CMD_DF_CLOSE, PLDM_FILE_CMD_DF_READ}},
#ifdef OEM_IBM
    {PLDM_OEM,
     {PLDM_HOST_GET_ALERT_STATUS, PLDM_GET_FILE_TABLE, PLDM_READ_FILE,
      PLDM_WRITE_FILE, PLDM_READ_FILE_INTO_MEMORY, PLDM_WRITE_FILE_FROM_MEMORY,
      PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY,
      PLDM_NEW_FILE_AVAILABLE, PLDM_READ_FILE_BY_TYPE, PLDM_WRITE_FILE_BY_TYPE,
      PLDM_FILE_ACK}},
#endif
};

static const std::map<Type, ver32_t> versions{
    {PLDM_BASE, {0x00, 0xf0, 0xf0, 0xf1}},
    {PLDM_PLATFORM, {0x00, 0xf0, 0xf2, 0xf1}},
    {PLDM_BIOS, {0x00, 0xf0, 0xf0, 0xf1}},
    {PLDM_FRU, {0x00, 0xf0, 0xf0, 0xf1}},
    {PLDM_FILE, {0x00, 0xf0, 0xf0, 0xf1}},
#ifdef OEM_IBM
    {PLDM_OEM, {0x00, 0xf0, 0xf0, 0xf1}},
#endif
};

static const std::vector<Type> multipartSupportedTypes{
    PLDM_FILE,
};

namespace base
{
Response Handler::getPLDMTypes(const pldm_msg* request,
                               size_t /*payloadLength*/)
{
    // DSP0240 has this as a bitfield8[N], where N = 0 to 7
    std::array<bitfield8_t, 8> types{};
    for (const auto& type : capabilities)
    {
        auto index = type.first / 8;
        // <Type Number> = <Array Index> * 8 + <bit position>
        auto bit = type.first - (index * 8);
        types[index].byte |= 1 << bit;
    }

    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_TYPES_RESP_BYTES, 0);
    auto responsePtr = new (response.data()) pldm_msg;
    auto rc = encode_get_types_resp(request->hdr.instance_id, PLDM_SUCCESS,
                                    types.data(), responsePtr);
    if (rc != PLDM_SUCCESS)
    {
        return CmdHandler::ccOnlyResponse(request, rc);
    }

    return response;
}

Response Handler::getPLDMCommands(const pldm_msg* request, size_t payloadLength)
{
    ver32_t version{};
    Type type;

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

    auto rc = decode_get_commands_req(request, payloadLength, &type, &version);

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

    // DSP0240 has this as a bitfield8[N], where N = 0 to 31
    std::array<bitfield8_t, 32> cmds{};
    if (!capabilities.contains(type))
    {
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_ERROR_INVALID_PLDM_TYPE);
    }

    for (const auto& cmd : capabilities.at(type))
    {
        auto index = cmd / 8;
        // <Type Number> = <Array Index> * 8 + <bit position>
        auto bit = cmd - (index * 8);
        cmds[index].byte |= 1 << bit;
    }

    rc = encode_get_commands_resp(request->hdr.instance_id, PLDM_SUCCESS,
                                  cmds.data(), responsePtr);
    if (rc != PLDM_SUCCESS)
    {
        return ccOnlyResponse(request, rc);
    }

    return response;
}

Response Handler::getPLDMVersion(const pldm_msg* request, size_t payloadLength)
{
    uint32_t transferHandle;
    Type type;
    uint8_t transferFlag;
    constexpr size_t checksumLen = sizeof(uint32_t);

    // Generate the response with 32bit checksum appended
    Response response(
        sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES + checksumLen, 0);
    auto responsePtr = new (response.data()) pldm_msg;

    uint8_t rc = decode_get_version_req(request, payloadLength, &transferHandle,
                                        &transferFlag, &type);

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

    ver32_t version{};
    auto search = versions.find(type);

    if (search == versions.end())
    {
        return CmdHandler::ccOnlyResponse(request,
                                          PLDM_ERROR_INVALID_PLDM_TYPE);
    }

    memcpy(&version, &(search->second), sizeof(version));
    rc = encode_get_version_resp(request->hdr.instance_id, PLDM_SUCCESS, 0,
                                 PLDM_START_AND_END, &version,
                                 sizeof(pldm_version), responsePtr);

    // Calculate the crc32
    uint32_t checksum = pldm_edac_crc32(&version, sizeof(version));
    checksum = htole32(checksum);
    memcpy(response.data() + sizeof(pldm_msg_hdr) + PLDM_GET_VERSION_RESP_BYTES,
           &checksum, checksumLen);

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

    return response;
}

void Handler::_processSetEventReceiver(sdeventplus::source::EventBase&
                                       /*source */)
{
    survEvent.reset();
    oemPlatformHandler->processSetEventReceiver();
}

Response Handler::getTID(const pldm_msg* request, size_t /*payloadLength*/)
{
    Response response(sizeof(pldm_msg_hdr) + PLDM_GET_TID_RESP_BYTES, 0);
    auto responsePtr = new (response.data()) pldm_msg;
    auto rc = encode_get_tid_resp(request->hdr.instance_id, PLDM_SUCCESS,
                                  TERMINUS_ID, responsePtr);
    if (rc != PLDM_SUCCESS)
    {
        return ccOnlyResponse(request, rc);
    }

    if (oemPlatformHandler)
    {
        survEvent = std::make_unique<sdeventplus::source::Defer>(
            event, [this](sdeventplus::source::EventBase& source) {
                this->_processSetEventReceiver(source);
            });
    }

    return response;
}

Response Handler::getNegotiateTransferParam(
    pldm_tid_t tid, const pldm_msg* request, size_t payloadLength)
{
    struct pldm_base_negotiate_transfer_params_resp resp_payload_struct = {};
    struct pldm_base_negotiate_transfer_params_req decoded_req;
    Response response(sizeof(pldm_msg_hdr) +
                          PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES,
                      0);
    auto responsePtr = reinterpret_cast<pldm_msg*>(response.data());

    int rc = decode_pldm_base_negotiate_transfer_params_req(
        request, payloadLength, &decoded_req);
    if (rc != 0)
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    // Part size should be a power of 2 and greater than PLDM_MIN_PART_SIZE
    if ((decoded_req.requester_part_size < PLDM_MIN_PART_SIZE) ||
        !std::has_single_bit(decoded_req.requester_part_size))
    {
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_DATA);
    }

    // Only check the multipart types supported by the responder
    for (const auto& type : multipartSupportedTypes)
    {
        if (type > PLDM_TYPES_MAX)
        {
            error("Invalid type '{TYPE}'", "TYPE", type);
            return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
        }

        // In the decoded_req.requester_protocol_support array, pldm type is
        // array_index * 8 + bit
        auto index = type / 8;
        auto bit = type % 8;

        if (decoded_req.requester_protocol_support[index].byte & (1 << bit))
        {
            std::map<uint8_t, uint16_t>& type_map_for_tid =
                negotiatedPartSizes[tid];
            type_map_for_tid[type] =
                std::min(decoded_req.requester_part_size,
                         (uint16_t)PLDM_RESPONDER_PART_SIZE);

            info(
                "Multipart negotiated for tid:'{TID}' type:'{TYPE}' size:'{SIZE}'",
                "TID", tid, "TYPE", type, "SIZE",
                (uint16_t)type_map_for_tid[type]);
        }

        resp_payload_struct.responder_protocol_support[index].byte |=
            static_cast<uint8_t>(1 << bit);
    }

    resp_payload_struct.completion_code = PLDM_SUCCESS;
    resp_payload_struct.responder_part_size = PLDM_RESPONDER_PART_SIZE;

    size_t respPayloadLength =
        PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES;
    rc = encode_pldm_base_negotiate_transfer_params_resp(
        request->hdr.instance_id, &resp_payload_struct, responsePtr,
        &respPayloadLength);
    if (rc != 0)
    {
        return ccOnlyResponse(request, PLDM_ERROR);
    }

    return response;
}

uint16_t Handler::getNegotiatedPartSize(pldm_tid_t tid, uint8_t pldmType)
{
    auto tid_it = negotiatedPartSizes.find(tid);
    if (tid_it == negotiatedPartSizes.end())
    {
        return PLDM_MIN_PART_SIZE;
    }

    auto type_it = tid_it->second.find(pldmType);
    if (type_it == tid_it->second.end())
    {
        return PLDM_MIN_PART_SIZE;
    }

    return type_it->second;
}

Response Handler::getMultipartReceive(pldm_tid_t tid, const pldm_msg* request,
                                      size_t payloadLength)
{
    if (payloadLength != PLDM_MULTIPART_RECEIVE_REQ_BYTES)
    {
        error("Invalid MultipartReceive request length. Received: '{LEN}'",
              "LEN", payloadLength);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH);
    }

    // First byte in the payload is the sub PLDM type.
    uint8_t pldmType = *request->payload;

    auto it = multipartReceivehandlers.find(pldmType);
    if (it == multipartReceivehandlers.end())
    {
        error("No multipart receive handler registered for PLDM type '{TYPE}'",
              "TYPE", pldmType);
        return CmdHandler::ccOnlyResponse(request, PLDM_ERROR);
    }

    return it->second->handleMultipartReceive(tid, request, payloadLength);
}

void Handler::registerMultipartReceiveHandler(uint8_t pldmType,
                                              CmdHandler* handler)
{
    multipartReceivehandlers.emplace(pldmType, handler);
}

} // namespace base
} // namespace responder
} // namespace pldm
