#include "config.h"

#include "iei_oem.hpp"

#include "sdbus_wrapper.hpp"
#include "utils.hpp"

#include <ipmid/api.h>

#include <phosphor-logging/lg2.hpp>

#include <optional>

namespace
{
constexpr auto FIRMWARE_TYPE_OFFSET = 0;
constexpr auto FIRMWARE_TYPE_SIZE = 1;
constexpr auto FIRMWARE_VERSION_OFFSET = FIRMWARE_TYPE_OFFSET +
                                         FIRMWARE_TYPE_SIZE;
constexpr auto FIRMWARE_VERSION_SIZE = 15;
constexpr auto FIRMWARE_BUILDTIME_OFFSET = FIRMWARE_VERSION_OFFSET +
                                           FIRMWARE_VERSION_SIZE;
constexpr auto FIRMWARE_BUILDTIME_SIZE = 20;
constexpr auto FIRMWARE_MIN_SIZE = FIRMWARE_BUILDTIME_OFFSET;

static_assert(FIRMWARE_VERSION_OFFSET == 1);
static_assert(FIRMWARE_BUILDTIME_OFFSET == 16);
} // namespace

namespace ipmi
{

#define UNUSED(x) (void)(x)

using namespace iei;

static void registerOEMFunctions() __attribute__((constructor));
static auto& bus = getBus();

struct ParsedAssetInfo
{
    uint8_t rwFlag;
    uint8_t deviceType;
    uint8_t infoType;
    uint8_t maskAllPresentLen;
    std::vector<uint8_t> enableStatus;
    std::vector<uint8_t> maskPresent;
    std::vector<uint8_t> maskAllPresent;
    uint8_t allInfoDone;
    uint16_t totalMessageLen;
    std::vector<uint8_t> data;
};

void dumpAssetInfo(const ParsedAssetInfo& info)
{
    fprintf(stderr,
            "AssetInfo: rw %d, deviceType 0x%02x, infoType 0x%02x, "
            "maskAllPresentLen %u\n",
            info.rwFlag, info.deviceType, info.infoType,
            info.maskAllPresentLen);
    fprintf(stderr, "enableStatus ");
    for (const auto& d : info.enableStatus)
    {
        fprintf(stderr, "0x%02x ", d);
    }
    fprintf(stderr, "\nmaskPresent ");
    for (const auto& d : info.maskPresent)
    {
        fprintf(stderr, "0x%02x ", d);
    }
    fprintf(stderr, "\nmaskAllPresent ");
    for (const auto& d : info.maskAllPresent)
    {
        fprintf(stderr, "0x%02x ", d);
    }
    fprintf(stderr, "\nallInfoDone %d, totalMessageLen %u\n", info.allInfoDone,
            info.totalMessageLen);
    fprintf(stderr, "data: ");
    for (const auto& d : info.data)
    {
        fprintf(stderr, "0x%02x ", d);
    }
    fprintf(stderr, "\n");
}

std::optional<ParsedAssetInfo> parseAssetInfo(const AssetInfoHeader* h)
{
    auto len = h->maskAllPresentLen;
    if (len == 0)
    {
        // This is invalid
        return {};
    }

    ParsedAssetInfo info;
    info.rwFlag = h->rwFlag;
    info.deviceType = h->deviceType;
    info.infoType = h->infoType;
    info.maskAllPresentLen = len;
    info.enableStatus.resize(len);
    info.maskPresent.resize(len);
    info.maskAllPresent.resize(len);
    const uint8_t* p = &h->enableStatus;
    memcpy(info.enableStatus.data(), p, len);
    p += len;
    memcpy(info.maskPresent.data(), p, len);
    p += len;
    memcpy(info.maskAllPresent.data(), p, len);
    p += len;
    info.allInfoDone = *p++;
    info.totalMessageLen = *reinterpret_cast<const uint16_t*>(p);
    p += sizeof(uint16_t);
    auto dataLen = info.totalMessageLen - (sizeof(AssetInfoHeader) + 3 * len);
    info.data.resize(dataLen);
    memcpy(info.data.data(), p, dataLen);

    //    dumpAssetInfo(info);
    return info;
}

void parseBIOSInfo(const std::vector<uint8_t>& data)
{
    if (data.size() < FIRMWARE_MIN_SIZE)
    {
        return;
    }
    bios_version_devname dev = static_cast<bios_version_devname>(data[0]);
    std::string version{data.data() + FIRMWARE_VERSION_OFFSET,
                        data.data() + FIRMWARE_VERSION_SIZE};
    std::string buildTime;
    if (dev == bios_version_devname::BIOS)
    {
        buildTime.assign(reinterpret_cast<const char*>(
                             data.data() + FIRMWARE_BUILDTIME_OFFSET),
                         FIRMWARE_BUILDTIME_SIZE);

        // Set BIOS version
        auto service = utils::getService(bus, BIOS_OBJPATH, VERSION_IFACE);
        utils::setProperty(bus, service.c_str(), BIOS_OBJPATH, VERSION_IFACE,
                           VERSION, version);
    }

    printf("Dev %s, version %s, build time %s\n",
           bios_devname[static_cast<int>(dev)].data(), version.c_str(),
           buildTime.c_str());
}

ipmi_ret_t ipmiOemIEIAssetInfo(ipmi_netfn_t /* netfn */, ipmi_cmd_t /* cmd */,
                               ipmi_request_t request, ipmi_response_t response,
                               ipmi_data_len_t /* data_len */,
                               ipmi_context_t /* context */)
{
    auto header = reinterpret_cast<AssetInfoHeader*>(request);
    uint8_t* res = reinterpret_cast<uint8_t*>(response);
    UNUSED(res);

    auto info = parseAssetInfo(header);
    auto deviceType = info->deviceType;
    if (deviceType != 0x05)
    {
        lg2::info("Device type ({DEVICE_TYPE}) not supported yet",
                  "DEVICE_TYPE", deviceType);
        return IPMI_CC_UNSPECIFIED_ERROR;
    }

    // For now we only support BIOS type
    parseBIOSInfo(info->data);

    return IPMI_CC_OK;
}

void registerOEMFunctions(void)
{
    ipmi_register_callback(NETFN_OEM_IEI, CMD_OEM_ASSET_INFO, nullptr,
                           ipmiOemIEIAssetInfo, SYSTEM_INTERFACE);
}

} // namespace ipmi
