#include "config.h"

#include "ipz_parser.hpp"

#include "vpdecc/vpdecc.h"

#include "constants.hpp"
#include "exceptions.hpp"

#include <nlohmann/json.hpp>

#include <typeindex>

namespace vpd
{

// Offset of different entries in VPD data.
enum Offset
{
    VHDR = 17,
    VHDR_TOC_ENTRY = 29,
    VTOC_PTR = 35,
    VTOC_REC_LEN = 37,
    VTOC_ECC_OFF = 39,
    VTOC_ECC_LEN = 41,
    VTOC_DATA = 13,
    VHDR_ECC = 0,
    VHDR_RECORD = 11
};

// Length of some specific entries w.r.t VPD data.
enum Length
{
    RECORD_NAME = 4,
    KW_NAME = 2,
    RECORD_OFFSET = 2,
    RECORD_MIN = 44,
    RECORD_LENGTH = 2,
    RECORD_ECC_OFFSET = 2,
    VHDR_ECC_LENGTH = 11,
    VHDR_RECORD_LENGTH = 44,
    RECORD_TYPE = 2,
    SKIP_A_RECORD_IN_PT = 14,
    JUMP_TO_RECORD_NAME = 6
}; // enum Length

/**
 * @brief API to read 2 bytes LE data.
 *
 * @param[in] iterator - iterator to VPD vector.
 * @return read bytes.
 */
static uint16_t readUInt16LE(types::BinaryVector::const_iterator iterator)
{
    uint16_t lowByte = *iterator;
    uint16_t highByte = *(iterator + 1);
    lowByte |= (highByte << 8);
    return lowByte;
}

bool IpzVpdParser::vhdrEccCheck()
{
    auto vpdPtr = m_vpdVector.cbegin();

    auto l_status = vpdecc_check_data(
        const_cast<uint8_t*>(&vpdPtr[Offset::VHDR_RECORD]),
        Length::VHDR_RECORD_LENGTH,
        const_cast<uint8_t*>(&vpdPtr[Offset::VHDR_ECC]),
        Length::VHDR_ECC_LENGTH);
    if (l_status == VPD_ECC_CORRECTABLE_DATA)
    {
        try
        {
            if (m_vpdFileStream.is_open())
            {
                m_vpdFileStream.seekp(m_vpdStartOffset + Offset::VHDR_RECORD,
                                      std::ios::beg);
                m_vpdFileStream.write(reinterpret_cast<const char*>(
                                          &m_vpdVector[Offset::VHDR_RECORD]),
                                      Length::VHDR_RECORD_LENGTH);
            }
            else
            {
                logging::logMessage("File not open");
                return false;
            }
        }
        catch (const std::fstream::failure& e)
        {
            logging::logMessage(
                "Error while operating on file with exception: " +
                std::string(e.what()));
            return false;
        }
    }
    else if (l_status != VPD_ECC_OK)
    {
        return false;
    }

    return true;
}

bool IpzVpdParser::vtocEccCheck()
{
    auto vpdPtr = m_vpdVector.cbegin();

    std::advance(vpdPtr, Offset::VTOC_PTR);

    // The offset to VTOC could be 1 or 2 bytes long
    auto vtocOffset = readUInt16LE(vpdPtr);

    // Get the VTOC Length
    std::advance(vpdPtr, sizeof(types::RecordOffset));
    auto vtocLength = readUInt16LE(vpdPtr);

    // Get the ECC Offset
    std::advance(vpdPtr, sizeof(types::RecordLength));
    auto vtocECCOffset = readUInt16LE(vpdPtr);

    // Get the ECC length
    std::advance(vpdPtr, sizeof(types::ECCOffset));
    auto vtocECCLength = readUInt16LE(vpdPtr);

    // Reset pointer to start of the vpd,
    // so that Offset will point to correct address
    vpdPtr = m_vpdVector.cbegin();
    auto l_status = vpdecc_check_data(
        const_cast<uint8_t*>(&m_vpdVector[vtocOffset]), vtocLength,
        const_cast<uint8_t*>(&m_vpdVector[vtocECCOffset]), vtocECCLength);
    if (l_status == VPD_ECC_CORRECTABLE_DATA)
    {
        try
        {
            if (m_vpdFileStream.is_open())
            {
                m_vpdFileStream.seekp(m_vpdStartOffset + vtocOffset,
                                      std::ios::beg);
                m_vpdFileStream.write(
                    reinterpret_cast<const char*>(&m_vpdVector[vtocOffset]),
                    vtocLength);
            }
            else
            {
                logging::logMessage("File not open");
                return false;
            }
        }
        catch (const std::fstream::failure& e)
        {
            logging::logMessage(
                "Error while operating on file with exception " +
                std::string(e.what()));
            return false;
        }
    }
    else if (l_status != VPD_ECC_OK)
    {
        return false;
    }

    return true;
}

bool IpzVpdParser::recordEccCheck(types::BinaryVector::const_iterator iterator)
{
    auto recordOffset = readUInt16LE(iterator);

    std::advance(iterator, sizeof(types::RecordOffset));
    auto recordLength = readUInt16LE(iterator);

    if (recordOffset == 0 || recordLength == 0)
    {
        throw(DataException("Invalid record offset or length"));
    }

    std::advance(iterator, sizeof(types::RecordLength));
    auto eccOffset = readUInt16LE(iterator);

    std::advance(iterator, sizeof(types::ECCOffset));
    auto eccLength = readUInt16LE(iterator);

    if (eccLength == 0 || eccOffset == 0)
    {
        throw(EccException("Invalid ECC length or offset."));
    }

    auto vpdPtr = m_vpdVector.cbegin();

    if (vpdecc_check_data(
            const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
            const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength) == VPD_ECC_OK)
    {
        return true;
    }

    return false;
}

void IpzVpdParser::checkHeader(types::BinaryVector::const_iterator itrToVPD)
{
    if (m_vpdVector.empty() || (Length::RECORD_MIN > m_vpdVector.size()))
    {
        throw(DataException("Malformed VPD"));
    }

    std::advance(itrToVPD, Offset::VHDR);
    auto stop = std::next(itrToVPD, Length::RECORD_NAME);

    std::string record(itrToVPD, stop);
    if ("VHDR" != record)
    {
        throw(DataException("VHDR record not found"));
    }

    if (!vhdrEccCheck())
    {
        throw(EccException("ERROR: VHDR ECC check Failed"));
    }
}

auto IpzVpdParser::readTOC(types::BinaryVector::const_iterator& itrToVPD)
{
    // The offset to VTOC could be 1 or 2 bytes long
    uint16_t vtocOffset =
        readUInt16LE((itrToVPD + Offset::VTOC_PTR)); // itrToVPD);

    // Got the offset to VTOC, skip past record header and keyword header
    // to get to the record name.
    std::advance(itrToVPD, vtocOffset + sizeof(types::RecordId) +
                               sizeof(types::RecordSize) +
                               // Skip past the RT keyword, which contains
                               // the record name.
                               Length::KW_NAME + sizeof(types::KwSize));

    std::string record(itrToVPD, std::next(itrToVPD, Length::RECORD_NAME));
    if ("VTOC" != record)
    {
        throw(DataException("VTOC record not found"));
    }

    if (!vtocEccCheck())
    {
        throw(EccException("ERROR: VTOC ECC check Failed"));
    }

    // VTOC record name is good, now read through the TOC, stored in the PT
    // PT keyword; vpdBuffer is now pointing at the first character of the
    // name 'VTOC', jump to PT data.
    // Skip past record name and KW name, 'PT'
    std::advance(itrToVPD, Length::RECORD_NAME + Length::KW_NAME);

    // Note size of PT
    auto ptLen = *itrToVPD;

    // Skip past PT size
    std::advance(itrToVPD, sizeof(types::KwSize));

    // length of PT keyword
    return ptLen;
}

types::RecordOffsetList IpzVpdParser::readPT(
    types::BinaryVector::const_iterator& itrToPT, auto ptLength)
{
    types::RecordOffsetList recordOffsets;

    auto end = itrToPT;
    std::advance(end, ptLength);

    // Look at each entry in the PT keyword. In the entry,
    // we care only about the record offset information.
    while (itrToPT < end)
    {
        std::string recordName(itrToPT, itrToPT + Length::RECORD_NAME);
        // Skip record name and record type
        std::advance(itrToPT, Length::RECORD_NAME + sizeof(types::RecordType));

        // Get record offset
        recordOffsets.push_back(readUInt16LE(itrToPT));
        try
        {
            // Verify the ECC for this Record
            if (!recordEccCheck(itrToPT))
            {
                throw(EccException("ERROR: ECC check failed"));
            }
        }
        catch (const EccException& ex)
        {
            logging::logMessage(ex.what());

            /*TODO: uncomment when PEL code goes in */

            /*std::string errMsg =
                std::string{ex.what()} + " Record: " + recordName;

            inventory::PelAdditionalData additionalData{};
            additionalData.emplace("DESCRIPTION", errMsg);
            additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
            createPEL(additionalData, PelSeverity::WARNING,
                      errIntfForEccCheckFail, nullptr);*/
        }
        catch (const DataException& ex)
        {
            logging::logMessage(ex.what());

            /*TODO: uncomment when PEL code goes in */

            /*std::string errMsg =
                std::string{ex.what()} + " Record: " + recordName;

            inventory::PelAdditionalData additionalData{};
            additionalData.emplace("DESCRIPTION", errMsg);
            additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
            createPEL(additionalData, PelSeverity::WARNING,
                      errIntfForInvalidVPD, nullptr);*/
        }

        // Jump record size, record length, ECC offset and ECC length
        std::advance(itrToPT,
                     sizeof(types::RecordOffset) + sizeof(types::RecordLength) +
                         sizeof(types::ECCOffset) + sizeof(types::ECCLength));
    }

    return recordOffsets;
}

types::IPZVpdMap::mapped_type IpzVpdParser::readKeywords(
    types::BinaryVector::const_iterator& itrToKwds)
{
    types::IPZVpdMap::mapped_type kwdValueMap{};
    while (true)
    {
        // Note keyword name
        std::string kwdName(itrToKwds, itrToKwds + Length::KW_NAME);
        if (constants::LAST_KW == kwdName)
        {
            // We're done
            break;
        }
        // Check if the Keyword is '#kw'
        char kwNameStart = *itrToKwds;

        // Jump past keyword name
        std::advance(itrToKwds, Length::KW_NAME);

        std::size_t kwdDataLength;
        std::size_t lengthHighByte;

        if (constants::POUND_KW == kwNameStart)
        {
            // Note keyword data length
            kwdDataLength = *itrToKwds;
            lengthHighByte = *(itrToKwds + 1);
            kwdDataLength |= (lengthHighByte << 8);

            // Jump past 2Byte keyword length
            std::advance(itrToKwds, sizeof(types::PoundKwSize));
        }
        else
        {
            // Note keyword data length
            kwdDataLength = *itrToKwds;

            // Jump past keyword length
            std::advance(itrToKwds, sizeof(types::KwSize));
        }

        // support all the Keywords
        auto stop = std::next(itrToKwds, kwdDataLength);
        std::string kwdata(itrToKwds, stop);
        kwdValueMap.emplace(std::move(kwdName), std::move(kwdata));

        // Jump past keyword data length
        std::advance(itrToKwds, kwdDataLength);
    }

    return kwdValueMap;
}

void IpzVpdParser::processRecord(auto recordOffset)
{
    // Jump to record name
    auto recordNameOffset =
        recordOffset + sizeof(types::RecordId) + sizeof(types::RecordSize) +
        // Skip past the RT keyword, which contains
        // the record name.
        Length::KW_NAME + sizeof(types::KwSize);

    // Get record name
    auto itrToVPDStart = m_vpdVector.cbegin();
    std::advance(itrToVPDStart, recordNameOffset);

    std::string recordName(itrToVPDStart, itrToVPDStart + Length::RECORD_NAME);

    // proceed to find contained keywords and their values.
    std::advance(itrToVPDStart, Length::RECORD_NAME);

    // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
    std::advance(itrToVPDStart, -(Length::KW_NAME + sizeof(types::KwSize) +
                                  Length::RECORD_NAME));

    // Add entry for this record (and contained keyword:value pairs)
    // to the parsed vpd output.
    m_parsedVPDMap.emplace(std::move(recordName),
                           std::move(readKeywords(itrToVPDStart)));
}

types::VPDMapVariant IpzVpdParser::parse()
{
    try
    {
        auto itrToVPD = m_vpdVector.cbegin();

        // Check vaidity of VHDR record
        checkHeader(itrToVPD);

        // Read the table of contents
        auto ptLen = readTOC(itrToVPD);

        // Read the table of contents record, to get offsets
        // to other records.
        auto recordOffsets = readPT(itrToVPD, ptLen);
        for (const auto& offset : recordOffsets)
        {
            processRecord(offset);
        }

        return m_parsedVPDMap;
    }
    catch (const std::exception& e)
    {
        logging::logMessage(e.what());
        throw e;
    }
}

types::BinaryVector IpzVpdParser::getKeywordValueFromRecord(
    const types::Record& i_recordName, const types::Keyword& i_keywordName,
    const types::RecordOffset& i_recordDataOffset)
{
    auto l_iterator = m_vpdVector.cbegin();

    // Go to the record name in the given record's offset
    std::ranges::advance(l_iterator,
                         i_recordDataOffset + Length::JUMP_TO_RECORD_NAME,
                         m_vpdVector.cend());

    // Check if the record is present in the given record's offset
    if (i_recordName !=
        std::string(l_iterator,
                    std::ranges::next(l_iterator, Length::RECORD_NAME,
                                      m_vpdVector.cend())))
    {
        throw std::runtime_error(
            "Given record is not present in the offset provided");
    }

    std::ranges::advance(l_iterator, Length::RECORD_NAME, m_vpdVector.cend());

    std::string l_kwName = std::string(
        l_iterator,
        std::ranges::next(l_iterator, Length::KW_NAME, m_vpdVector.cend()));

    // Iterate through the keywords until the last keyword PF is found.
    while (l_kwName != constants::LAST_KW)
    {
        // First character required for #D keyword check
        char l_kwNameStart = *l_iterator;

        std::ranges::advance(l_iterator, Length::KW_NAME, m_vpdVector.cend());

        // Get the keyword's data length
        auto l_kwdDataLength = 0;

        if (constants::POUND_KW == l_kwNameStart)
        {
            l_kwdDataLength = readUInt16LE(l_iterator);
            std::ranges::advance(l_iterator, sizeof(types::PoundKwSize),
                                 m_vpdVector.cend());
        }
        else
        {
            l_kwdDataLength = *l_iterator;
            std::ranges::advance(l_iterator, sizeof(types::KwSize),
                                 m_vpdVector.cend());
        }

        if (l_kwName == i_keywordName)
        {
            // Return keyword's value to the caller
            return types::BinaryVector(
                l_iterator, std::ranges::next(l_iterator, l_kwdDataLength,
                                              m_vpdVector.cend()));
        }

        // next keyword search
        std::ranges::advance(l_iterator, l_kwdDataLength, m_vpdVector.cend());

        // next keyword name
        l_kwName = std::string(
            l_iterator,
            std::ranges::next(l_iterator, Length::KW_NAME, m_vpdVector.cend()));
    }

    // Keyword not found
    throw std::runtime_error("Given keyword not found.");
}

types::RecordData IpzVpdParser::getRecordDetailsFromVTOC(
    const types::Record& i_recordName, const types::RecordOffset& i_vtocOffset)
{
    // Get VTOC's PT keyword value.
    const auto l_vtocPTKwValue =
        getKeywordValueFromRecord("VTOC", "PT", i_vtocOffset);

    // Parse through VTOC PT keyword value to find the record which we are
    // interested in.
    auto l_vtocPTItr = l_vtocPTKwValue.cbegin();

    types::RecordData l_recordData;

    while (l_vtocPTItr < l_vtocPTKwValue.cend())
    {
        if (i_recordName ==
            std::string(l_vtocPTItr, l_vtocPTItr + Length::RECORD_NAME))
        {
            // Record found in VTOC PT keyword. Get offset
            std::ranges::advance(l_vtocPTItr,
                                 Length::RECORD_NAME + Length::RECORD_TYPE,
                                 l_vtocPTKwValue.cend());
            const auto l_recordOffset = readUInt16LE(l_vtocPTItr);

            std::ranges::advance(l_vtocPTItr, Length::RECORD_OFFSET,
                                 l_vtocPTKwValue.cend());
            const auto l_recordLength = readUInt16LE(l_vtocPTItr);

            std::ranges::advance(l_vtocPTItr, Length::RECORD_LENGTH,
                                 l_vtocPTKwValue.cend());
            const auto l_eccOffset = readUInt16LE(l_vtocPTItr);

            std::ranges::advance(l_vtocPTItr, Length::RECORD_ECC_OFFSET,
                                 l_vtocPTKwValue.cend());
            const auto l_eccLength = readUInt16LE(l_vtocPTItr);

            l_recordData = std::make_tuple(l_recordOffset, l_recordLength,
                                           l_eccOffset, l_eccLength);
            break;
        }

        std::ranges::advance(l_vtocPTItr, Length::SKIP_A_RECORD_IN_PT,
                             l_vtocPTKwValue.cend());
    }

    return l_recordData;
}

types::DbusVariantType IpzVpdParser::readKeywordFromHardware(
    const types::ReadVpdParams i_paramsToReadData)
{
    // Extract record and keyword from i_paramsToReadData
    types::Record l_record;
    types::Keyword l_keyword;

    if (const types::IpzType* l_ipzData =
            std::get_if<types::IpzType>(&i_paramsToReadData))
    {
        l_record = std::get<0>(*l_ipzData);
        l_keyword = std::get<1>(*l_ipzData);
    }
    else
    {
        logging::logMessage(
            "Input parameter type provided isn't compatible with the given VPD type.");
        throw types::DbusInvalidArgument();
    }

    // Read keyword's value from vector
    auto l_itrToVPD = m_vpdVector.cbegin();

    if (l_record == "VHDR")
    {
// Disable providing a way to read keywords from VHDR for the time being.
#if 0
        std::ranges::advance(l_itrToVPD, Offset::VHDR_RECORD,
                             m_vpdVector.cend());

        return types::DbusVariantType{getKeywordValueFromRecord(
            l_record, l_keyword, Offset::VHDR_RECORD)};
#endif

        logging::logMessage("Read cannot be performed on VHDR record.");
        throw types::DbusInvalidArgument();
    }

    // Get VTOC offset
    std::ranges::advance(l_itrToVPD, Offset::VTOC_PTR, m_vpdVector.cend());
    auto l_vtocOffset = readUInt16LE(l_itrToVPD);

    if (l_record == "VTOC")
    {
        // Disable providing a way to read keywords from VTOC for the time
        // being.
#if 0
        return types::DbusVariantType{
            getKeywordValueFromRecord(l_record, l_keyword, l_vtocOffset)};
#endif

        logging::logMessage("Read cannot be performed on VTOC record.");
        throw types::DbusInvalidArgument();
    }

    // Get record offset from VTOC's PT keyword value.
    auto l_recordData = getRecordDetailsFromVTOC(l_record, l_vtocOffset);
    const auto l_recordOffset = std::get<0>(l_recordData);

    if (l_recordOffset == 0)
    {
        throw std::runtime_error("Record not found in VTOC PT keyword.");
    }

    // Get the given keyword's value
    return types::DbusVariantType{
        getKeywordValueFromRecord(l_record, l_keyword, l_recordOffset)};
}

void IpzVpdParser::updateRecordECC(
    const auto& i_recordDataOffset, const auto& i_recordDataLength,
    const auto& i_recordECCOffset, size_t i_recordECCLength,
    types::BinaryVector& io_vpdVector)
{
    auto l_recordDataBegin =
        std::next(io_vpdVector.begin(), i_recordDataOffset);

    auto l_recordECCBegin = std::next(io_vpdVector.begin(), i_recordECCOffset);

    auto l_eccStatus = vpdecc_create_ecc(
        const_cast<uint8_t*>(&l_recordDataBegin[0]), i_recordDataLength,
        const_cast<uint8_t*>(&l_recordECCBegin[0]), &i_recordECCLength);

    if (l_eccStatus != VPD_ECC_OK)
    {
        throw(EccException("ECC update failed with error " + l_eccStatus));
    }

    auto l_recordECCEnd = std::next(l_recordECCBegin, i_recordECCLength);

    m_vpdFileStream.seekp(m_vpdStartOffset + i_recordECCOffset, std::ios::beg);

    std::copy(l_recordECCBegin, l_recordECCEnd,
              std::ostreambuf_iterator<char>(m_vpdFileStream));
}

int IpzVpdParser::setKeywordValueInRecord(
    const types::Record& i_recordName, const types::Keyword& i_keywordName,
    const types::BinaryVector& i_keywordData,
    const types::RecordOffset& i_recordDataOffset,
    types::BinaryVector& io_vpdVector)
{
    auto l_iterator = io_vpdVector.begin();

    // Go to the record name in the given record's offset
    std::ranges::advance(l_iterator,
                         i_recordDataOffset + Length::JUMP_TO_RECORD_NAME,
                         io_vpdVector.end());

    const std::string l_recordFound(
        l_iterator,
        std::ranges::next(l_iterator, Length::RECORD_NAME, io_vpdVector.end()));

    // Check if the record is present in the given record's offset
    if (i_recordName != l_recordFound)
    {
        throw(DataException("Given record found at the offset " +
                            std::to_string(i_recordDataOffset) + " is : " +
                            l_recordFound + " and not " + i_recordName));
    }

    std::ranges::advance(l_iterator, Length::RECORD_NAME, io_vpdVector.end());

    std::string l_kwName = std::string(
        l_iterator,
        std::ranges::next(l_iterator, Length::KW_NAME, io_vpdVector.end()));

    // Iterate through the keywords until the last keyword PF is found.
    while (l_kwName != constants::LAST_KW)
    {
        // First character required for #D keyword check
        char l_kwNameStart = *l_iterator;

        std::ranges::advance(l_iterator, Length::KW_NAME, io_vpdVector.end());

        // Find the keyword's data length
        size_t l_kwdDataLength = 0;

        if (constants::POUND_KW == l_kwNameStart)
        {
            l_kwdDataLength = readUInt16LE(l_iterator);
            std::ranges::advance(l_iterator, sizeof(types::PoundKwSize),
                                 io_vpdVector.end());
        }
        else
        {
            l_kwdDataLength = *l_iterator;
            std::ranges::advance(l_iterator, sizeof(types::KwSize),
                                 io_vpdVector.end());
        }

        if (l_kwName == i_keywordName)
        {
            // Before writing the keyword's value, get the maximum size that can
            // be updated.
            const auto l_lengthToUpdate =
                i_keywordData.size() <= l_kwdDataLength
                    ? i_keywordData.size()
                    : l_kwdDataLength;

            // Set the keyword's value on vector. This is required to update the
            // record's ECC based on the new value set.
            const auto i_keywordDataEnd = std::ranges::next(
                i_keywordData.cbegin(), l_lengthToUpdate, i_keywordData.cend());

            std::copy(i_keywordData.cbegin(), i_keywordDataEnd, l_iterator);

            // Set the keyword's value on hardware
            const auto l_kwdDataOffset =
                std::distance(io_vpdVector.begin(), l_iterator);
            m_vpdFileStream.seekp(m_vpdStartOffset + l_kwdDataOffset,
                                  std::ios::beg);

            std::copy(i_keywordData.cbegin(), i_keywordDataEnd,
                      std::ostreambuf_iterator<char>(m_vpdFileStream));

            // return no of bytes set
            return l_lengthToUpdate;
        }

        // next keyword search
        std::ranges::advance(l_iterator, l_kwdDataLength, io_vpdVector.end());

        // next keyword name
        l_kwName = std::string(
            l_iterator,
            std::ranges::next(l_iterator, Length::KW_NAME, io_vpdVector.end()));
    }

    // Keyword not found
    throw(DataException(
        "Keyword " + i_keywordName + " not found in record " + i_recordName));
}

int IpzVpdParser::writeKeywordOnHardware(
    const types::WriteVpdParams i_paramsToWriteData)
{
    int l_sizeWritten = -1;

    try
    {
        types::Record l_recordName;
        types::Keyword l_keywordName;
        types::BinaryVector l_keywordData;

        // Extract record, keyword and value from i_paramsToWriteData
        if (const types::IpzData* l_ipzData =
                std::get_if<types::IpzData>(&i_paramsToWriteData))
        {
            l_recordName = std::get<0>(*l_ipzData);
            l_keywordName = std::get<1>(*l_ipzData);
            l_keywordData = std::get<2>(*l_ipzData);
        }
        else
        {
            logging::logMessage(
                "Input parameter type provided isn't compatible with the given FRU's VPD type.");
            throw types::DbusInvalidArgument();
        }

        if (l_recordName == "VHDR" || l_recordName == "VTOC")
        {
            logging::logMessage(
                "Write operation not allowed on the given record : " +
                l_recordName);
            throw types::DbusNotAllowed();
        }

        if (l_keywordData.size() == 0)
        {
            logging::logMessage(
                "Write operation not allowed as the given keyword's data length is 0.");
            throw types::DbusInvalidArgument();
        }

        auto l_vpdBegin = m_vpdVector.begin();

        // Get VTOC offset
        std::ranges::advance(l_vpdBegin, Offset::VTOC_PTR, m_vpdVector.end());
        auto l_vtocOffset = readUInt16LE(l_vpdBegin);

        // Get the details of user given record from VTOC
        const types::RecordData& l_inputRecordDetails =
            getRecordDetailsFromVTOC(l_recordName, l_vtocOffset);

        const auto& l_inputRecordOffset = std::get<0>(l_inputRecordDetails);

        if (l_inputRecordOffset == 0)
        {
            throw(DataException("Record not found in VTOC PT keyword."));
        }

        // Create a local copy of m_vpdVector to perform keyword update and ecc
        // update on filestream.
        types::BinaryVector l_vpdVector = m_vpdVector;

        // write keyword's value on hardware
        l_sizeWritten =
            setKeywordValueInRecord(l_recordName, l_keywordName, l_keywordData,
                                    l_inputRecordOffset, l_vpdVector);

        if (l_sizeWritten <= 0)
        {
            throw(DataException("Unable to set value on " + l_recordName + ":" +
                                l_keywordName));
        }

        // Update the record's ECC
        updateRecordECC(l_inputRecordOffset, std::get<1>(l_inputRecordDetails),
                        std::get<2>(l_inputRecordDetails),
                        std::get<3>(l_inputRecordDetails), l_vpdVector);

        logging::logMessage(std::to_string(l_sizeWritten) +
                            " bytes updated successfully on hardware for " +
                            l_recordName + ":" + l_keywordName);
    }
    catch (const std::exception& l_exception)
    {
        throw;
    }

    return l_sizeWritten;
}
} // namespace vpd
