#include "config.h"

#include "worker.hpp"

#include "backup_restore.hpp"
#include "configuration.hpp"
#include "constants.hpp"
#include "event_logger.hpp"
#include "exceptions.hpp"
#include "logger.hpp"
#include "parser.hpp"
#include "parser_factory.hpp"
#include "parser_interface.hpp"

#include <utility/dbus_utility.hpp>
#include <utility/json_utility.hpp>
#include <utility/vpd_specific_utility.hpp>

#include <filesystem>
#include <fstream>
#include <future>
#include <typeindex>
#include <unordered_set>

namespace vpd
{

Worker::Worker(std::string pathToConfigJson, uint8_t i_maxThreadCount) :
    m_configJsonPath(pathToConfigJson), m_semaphore(i_maxThreadCount)
{
    // Implies the processing is based on some config JSON
    if (!m_configJsonPath.empty())
    {
        // Check if symlink is already there to confirm fresh boot/factory
        // reset.
        if (std::filesystem::exists(INVENTORY_JSON_SYM_LINK))
        {
            logging::logMessage("Sym Link already present");
            m_configJsonPath = INVENTORY_JSON_SYM_LINK;
            m_isSymlinkPresent = true;
        }

        try
        {
            m_parsedJson = jsonUtility::getParsedJson(m_configJsonPath);

            // check for mandatory fields at this point itself.
            if (!m_parsedJson.contains("frus"))
            {
                throw std::runtime_error("Mandatory tag(s) missing from JSON");
            }
        }
        catch (const std::exception& ex)
        {
            throw(JsonException(ex.what(), m_configJsonPath));
        }
    }
    else
    {
        logging::logMessage("Processing in not based on any config JSON");
    }
}

static std::string readFitConfigValue()
{
    std::vector<std::string> output =
        commonUtility::executeCmd("/sbin/fw_printenv");
    std::string fitConfigValue;

    for (const auto& entry : output)
    {
        auto pos = entry.find("=");
        auto key = entry.substr(0, pos);
        if (key != "fitconfig")
        {
            continue;
        }

        if (pos + 1 < entry.size())
        {
            fitConfigValue = entry.substr(pos + 1);
        }
    }

    return fitConfigValue;
}

bool Worker::isSystemVPDOnDBus() const
{
    const std::string& mboardPath =
        m_parsedJson["frus"][SYSTEM_VPD_FILE_PATH].at(0).value(
            "inventoryPath", "");

    if (mboardPath.empty())
    {
        throw JsonException("System vpd file path missing in JSON",
                            INVENTORY_JSON_SYM_LINK);
    }

    std::array<const char*, 1> interfaces = {
        "xyz.openbmc_project.Inventory.Item.Board.Motherboard"};

    const types::MapperGetObject& objectMap =
        dbusUtility::getObjectMap(mboardPath, interfaces);

    if (objectMap.empty())
    {
        return false;
    }
    return true;
}

std::string Worker::getIMValue(const types::IPZVpdMap& parsedVpd) const
{
    if (parsedVpd.empty())
    {
        throw std::runtime_error("Empty VPD map. Can't Extract IM value");
    }

    const auto& itrToVSBP = parsedVpd.find("VSBP");
    if (itrToVSBP == parsedVpd.end())
    {
        throw DataException("VSBP record missing.");
    }

    const auto& itrToIM = (itrToVSBP->second).find("IM");
    if (itrToIM == (itrToVSBP->second).end())
    {
        throw DataException("IM keyword missing.");
    }

    types::BinaryVector imVal;
    std::copy(itrToIM->second.begin(), itrToIM->second.end(),
              back_inserter(imVal));

    std::ostringstream imData;
    for (auto& aByte : imVal)
    {
        imData << std::setw(2) << std::setfill('0') << std::hex
               << static_cast<int>(aByte);
    }

    return imData.str();
}

std::string Worker::getHWVersion(const types::IPZVpdMap& parsedVpd) const
{
    if (parsedVpd.empty())
    {
        throw std::runtime_error("Empty VPD map. Can't Extract HW value");
    }

    const auto& itrToVINI = parsedVpd.find("VINI");
    if (itrToVINI == parsedVpd.end())
    {
        throw DataException("VINI record missing.");
    }

    const auto& itrToHW = (itrToVINI->second).find("HW");
    if (itrToHW == (itrToVINI->second).end())
    {
        throw DataException("HW keyword missing.");
    }

    types::BinaryVector hwVal;
    std::copy(itrToHW->second.begin(), itrToHW->second.end(),
              back_inserter(hwVal));

    // The planar pass only comes from the LSB of the HW keyword,
    // where as the MSB is used for other purposes such as signifying clock
    // termination.
    hwVal[0] = 0x00;

    std::ostringstream hwString;
    for (auto& aByte : hwVal)
    {
        hwString << std::setw(2) << std::setfill('0') << std::hex
                 << static_cast<int>(aByte);
    }

    return hwString.str();
}

void Worker::fillVPDMap(const std::string& vpdFilePath,
                        types::VPDMapVariant& vpdMap)
{
    logging::logMessage(std::string("Parsing file = ") + vpdFilePath);

    if (vpdFilePath.empty())
    {
        throw std::runtime_error("Invalid file path passed to fillVPDMap API.");
    }

    if (!std::filesystem::exists(vpdFilePath))
    {
        throw std::runtime_error("Can't Find physical file");
    }

    std::shared_ptr<Parser> vpdParser =
        std::make_shared<Parser>(vpdFilePath, m_parsedJson);
    vpdMap = vpdParser->parse();
}

void Worker::getSystemJson(std::string& systemJson,
                           const types::VPDMapVariant& parsedVpdMap)
{
    if (auto pVal = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        std::string hwKWdValue = getHWVersion(*pVal);
        if (hwKWdValue.empty())
        {
            throw DataException("HW value fetched is empty.");
        }

        const std::string& imKwdValue = getIMValue(*pVal);
        if (imKwdValue.empty())
        {
            throw DataException("IM value fetched is empty.");
        }

        auto itrToIM = config::systemType.find(imKwdValue);
        if (itrToIM == config::systemType.end())
        {
            throw DataException("IM keyword does not map to any system type");
        }

        const types::HWVerList hwVersionList = itrToIM->second.second;
        if (!hwVersionList.empty())
        {
            transform(hwKWdValue.begin(), hwKWdValue.end(), hwKWdValue.begin(),
                      ::toupper);

            auto itrToHW =
                std::find_if(hwVersionList.begin(), hwVersionList.end(),
                             [&hwKWdValue](const auto& aPair) {
                                 return aPair.first == hwKWdValue;
                             });

            if (itrToHW != hwVersionList.end())
            {
                if (!(*itrToHW).second.empty())
                {
                    systemJson += (*itrToIM).first + "_" + (*itrToHW).second +
                                  ".json";
                }
                else
                {
                    systemJson += (*itrToIM).first + ".json";
                }
                return;
            }
        }
        systemJson += itrToIM->second.first + ".json";
        return;
    }

    throw DataException(
        "Invalid VPD type returned from Parser. Can't get system JSON.");
}

static void setEnvAndReboot(const std::string& key, const std::string& value)
{
    // set env and reboot and break.
    commonUtility::executeCmd("/sbin/fw_setenv", key, value);
    logging::logMessage("Rebooting BMC to pick up new device tree");

    // make dbus call to reboot
    auto bus = sdbusplus::bus::new_default_system();
    auto method = bus.new_method_call(
        "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
        "org.freedesktop.systemd1.Manager", "Reboot");
    bus.call_noreply(method);
}

void Worker::setJsonSymbolicLink(const std::string& i_systemJson)
{
    std::error_code l_ec;
    l_ec.clear();

    // Check if symlink file path exists and if the JSON at this location is a
    // symlink.
    if (m_isSymlinkPresent &&
        std::filesystem::is_symlink(INVENTORY_JSON_SYM_LINK, l_ec))
    { // Don't care about exception in "is_symlink". Will continue with creation
      // of symlink.

        const auto& l_symlinkFilePth =
            std::filesystem::read_symlink(INVENTORY_JSON_SYM_LINK, l_ec);

        if (l_ec)
        {
            logging::logMessage(
                "Can't read existing symlink. Error =" + l_ec.message() +
                "Trying removal of symlink and creation of new symlink.");
        }

        // If currently set JSON is the required one. No further processing
        // required.
        if (i_systemJson == l_symlinkFilePth)
        {
            // Correct symlink already set.
            return;
        }

        if (!std::filesystem::remove(INVENTORY_JSON_SYM_LINK, l_ec))
        {
            // No point going further. If removal fails for existing symlink,
            // create will anyways throw.
            throw std::runtime_error(
                "Removal of symlink failed with Error = " + l_ec.message() +
                ". Can't proceed with create_symlink.");
        }
    }

    if (!std::filesystem::exists(VPD_SYMLIMK_PATH, l_ec))
    {
        if (l_ec)
        {
            throw std::runtime_error(
                "File system call to exist failed with error = " +
                l_ec.message());
        }

        // implies it is a fresh boot/factory reset.
        // Create the directory for hosting the symlink
        if (!std::filesystem::create_directories(VPD_SYMLIMK_PATH, l_ec))
        {
            if (l_ec)
            {
                throw std::runtime_error(
                    "File system call to create directory failed with error = " +
                    l_ec.message());
            }
        }
    }

    // create a new symlink based on the system
    std::filesystem::create_symlink(i_systemJson, INVENTORY_JSON_SYM_LINK,
                                    l_ec);

    if (l_ec)
    {
        throw std::runtime_error(
            "create_symlink system call failed with error: " + l_ec.message());
    }

    // If the flow is at this point implies the symlink was not present there.
    // Considering this as factory reset.
    m_isFactoryResetDone = true;
}

void Worker::setDeviceTreeAndJson()
{
    // JSON is madatory for processing of this API.
    if (m_parsedJson.empty())
    {
        throw JsonException("System config JSON is empty", m_configJsonPath);
    }

    types::VPDMapVariant parsedVpdMap;
    fillVPDMap(SYSTEM_VPD_FILE_PATH, parsedVpdMap);

    // Implies it is default JSON.
    std::string systemJson{JSON_ABSOLUTE_PATH_PREFIX};

    // ToDo: Need to check if INVENTORY_JSON_SYM_LINK pointing to correct system
    // This is required to support movement from rainier to Blue Ridge on the
    // fly.

    getSystemJson(systemJson, parsedVpdMap);

    if (!systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
    {
        throw DataException(
            "No system JSON found corresponding to IM read from VPD.");
    }

    // re-parse the JSON once appropriate JSON has been selected.
    m_parsedJson = jsonUtility::getParsedJson(systemJson);

    if (m_parsedJson.empty())
    {
        throw(JsonException("Json parsing failed", systemJson));
    }

    std::string devTreeFromJson;
    if (m_parsedJson.contains("devTree"))
    {
        devTreeFromJson = m_parsedJson["devTree"];

        if (devTreeFromJson.empty())
        {
            EventLogger::createSyncPel(
                types::ErrorType::JsonFailure, types::SeverityType::Error,
                __FILE__, __FUNCTION__, 0,
                "Mandatory value for device tree missing from JSON[" +
                    systemJson + "]",
                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
        }
    }

    auto fitConfigVal = readFitConfigValue();

    if (devTreeFromJson.empty() ||
        fitConfigVal.find(devTreeFromJson) != std::string::npos)
    { // Skipping setting device tree as either devtree info is missing from
      // Json or it is rightly set.

        setJsonSymbolicLink(systemJson);

        if (isSystemVPDOnDBus() &&
            jsonUtility::isBackupAndRestoreRequired(m_parsedJson))
        {
            performBackupAndRestore(parsedVpdMap);
        }

        // proceed to publish system VPD.
        publishSystemVPD(parsedVpdMap);
        return;
    }

    setEnvAndReboot("fitconfig", devTreeFromJson);
    exit(EXIT_SUCCESS);
}

void Worker::populateIPZVPDpropertyMap(
    types::InterfaceMap& interfacePropMap,
    const types::IPZKwdValueMap& keyordValueMap,
    const std::string& interfaceName)
{
    types::PropertyMap propertyValueMap;
    for (const auto& kwdVal : keyordValueMap)
    {
        auto kwd = kwdVal.first;

        if (kwd[0] == '#')
        {
            kwd = std::string("PD_") + kwd[1];
        }
        else if (isdigit(kwd[0]))
        {
            kwd = std::string("N_") + kwd;
        }

        types::BinaryVector value(kwdVal.second.begin(), kwdVal.second.end());
        propertyValueMap.emplace(move(kwd), move(value));
    }

    if (!propertyValueMap.empty())
    {
        interfacePropMap.emplace(interfaceName, propertyValueMap);
    }
}

void Worker::populateKwdVPDpropertyMap(const types::KeywordVpdMap& keyordVPDMap,
                                       types::InterfaceMap& interfaceMap)
{
    for (const auto& kwdValMap : keyordVPDMap)
    {
        types::PropertyMap propertyValueMap;
        auto kwd = kwdValMap.first;

        if (kwd[0] == '#')
        {
            kwd = std::string("PD_") + kwd[1];
        }
        else if (isdigit(kwd[0]))
        {
            kwd = std::string("N_") + kwd;
        }

        if (auto keywordValue = get_if<types::BinaryVector>(&kwdValMap.second))
        {
            types::BinaryVector value((*keywordValue).begin(),
                                      (*keywordValue).end());
            propertyValueMap.emplace(move(kwd), move(value));
        }
        else if (auto keywordValue = get_if<std::string>(&kwdValMap.second))
        {
            types::BinaryVector value((*keywordValue).begin(),
                                      (*keywordValue).end());
            propertyValueMap.emplace(move(kwd), move(value));
        }
        else if (auto keywordValue = get_if<size_t>(&kwdValMap.second))
        {
            if (kwd == "MemorySizeInKB")
            {
                types::PropertyMap memProp;
                memProp.emplace(move(kwd), ((*keywordValue)));
                interfaceMap.emplace("xyz.openbmc_project.Inventory.Item.Dimm",
                                     move(memProp));
                continue;
            }
            else
            {
                logging::logMessage(
                    "Unknown Keyword =" + kwd + " found in keyword VPD map");
                continue;
            }
        }
        else
        {
            logging::logMessage(
                "Unknown variant type found in keyword VPD map.");
            continue;
        }

        if (!propertyValueMap.empty())
        {
            vpdSpecificUtility::insertOrMerge(
                interfaceMap, constants::kwdVpdInf, move(propertyValueMap));
        }
    }
}

void Worker::populateInterfaces(const nlohmann::json& interfaceJson,
                                types::InterfaceMap& interfaceMap,
                                const types::VPDMapVariant& parsedVpdMap)
{
    for (const auto& interfacesPropPair : interfaceJson.items())
    {
        const std::string& interface = interfacesPropPair.key();
        types::PropertyMap propertyMap;

        for (const auto& propValuePair : interfacesPropPair.value().items())
        {
            const std::string property = propValuePair.key();

            if (propValuePair.value().is_boolean())
            {
                propertyMap.emplace(property,
                                    propValuePair.value().get<bool>());
            }
            else if (propValuePair.value().is_string())
            {
                if (property.compare("LocationCode") == 0 &&
                    interface.compare("com.ibm.ipzvpd.Location") == 0)
                {
                    std::string value =
                        vpdSpecificUtility::getExpandedLocationCode(
                            propValuePair.value().get<std::string>(),
                            parsedVpdMap);
                    propertyMap.emplace(property, value);

                    auto l_locCodeProperty = propertyMap;
                    vpdSpecificUtility::insertOrMerge(
                        interfaceMap,
                        std::string(constants::xyzLocationCodeInf),
                        move(l_locCodeProperty));
                }
                else
                {
                    propertyMap.emplace(
                        property, propValuePair.value().get<std::string>());
                }
            }
            else if (propValuePair.value().is_array())
            {
                try
                {
                    propertyMap.emplace(
                        property,
                        propValuePair.value().get<types::BinaryVector>());
                }
                catch (const nlohmann::detail::type_error& e)
                {
                    std::cerr << "Type exception: " << e.what() << "\n";
                }
            }
            else if (propValuePair.value().is_number())
            {
                // For now assume the value is a size_t.  In the future it would
                // be nice to come up with a way to get the type from the JSON.
                propertyMap.emplace(property,
                                    propValuePair.value().get<size_t>());
            }
            else if (propValuePair.value().is_object())
            {
                const std::string& record =
                    propValuePair.value().value("recordName", "");
                const std::string& keyword =
                    propValuePair.value().value("keywordName", "");
                const std::string& encoding =
                    propValuePair.value().value("encoding", "");

                if (auto ipzVpdMap =
                        std::get_if<types::IPZVpdMap>(&parsedVpdMap))
                {
                    if (!record.empty() && !keyword.empty() &&
                        (*ipzVpdMap).count(record) &&
                        (*ipzVpdMap).at(record).count(keyword))
                    {
                        auto encoded = vpdSpecificUtility::encodeKeyword(
                            ((*ipzVpdMap).at(record).at(keyword)), encoding);
                        propertyMap.emplace(property, encoded);
                    }
                }
                else if (auto kwdVpdMap =
                             std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
                {
                    if (!keyword.empty() && (*kwdVpdMap).count(keyword))
                    {
                        if (auto kwValue = std::get_if<types::BinaryVector>(
                                &(*kwdVpdMap).at(keyword)))
                        {
                            auto encodedValue =
                                vpdSpecificUtility::encodeKeyword(
                                    std::string((*kwValue).begin(),
                                                (*kwValue).end()),
                                    encoding);

                            propertyMap.emplace(property, encodedValue);
                        }
                        else if (auto kwValue = std::get_if<std::string>(
                                     &(*kwdVpdMap).at(keyword)))
                        {
                            auto encodedValue =
                                vpdSpecificUtility::encodeKeyword(
                                    std::string((*kwValue).begin(),
                                                (*kwValue).end()),
                                    encoding);

                            propertyMap.emplace(property, encodedValue);
                        }
                        else if (auto uintValue = std::get_if<size_t>(
                                     &(*kwdVpdMap).at(keyword)))
                        {
                            propertyMap.emplace(property, *uintValue);
                        }
                        else
                        {
                            logging::logMessage(
                                "Unknown keyword found, Keywrod = " + keyword);
                        }
                    }
                }
            }
        }
        vpdSpecificUtility::insertOrMerge(interfaceMap, interface,
                                          move(propertyMap));
    }
}

bool Worker::isCPUIOGoodOnly(const std::string& i_pgKeyword)
{
    const unsigned char l_io[] = {
        0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF,
        0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF, 0xE7, 0xF9, 0xFF};

    // EQ0 index (in PG keyword) starts at 97 (with offset starting from 0).
    // Each EQ carries 3 bytes of data. Totally there are 8 EQs. If all EQs'
    // value equals 0xE7F9FF, then the cpu has no good cores and its treated as
    // IO.
    if (memcmp(l_io, i_pgKeyword.data() + constants::INDEX_OF_EQ0_IN_PG,
               constants::SIZE_OF_8EQ_IN_PG) == 0)
    {
        return true;
    }

    // The CPU is not an IO
    return false;
}

bool Worker::primeInventory(const std::string& i_vpdFilePath)
{
    if (i_vpdFilePath.empty())
    {
        logging::logMessage("Empty VPD file path given");
        return false;
    }

    if (m_parsedJson.empty())
    {
        logging::logMessage("Empty JSON detected for " + i_vpdFilePath);
        return false;
    }
    else if (!m_parsedJson["frus"].contains(i_vpdFilePath))
    {
        logging::logMessage("File " + i_vpdFilePath +
                            ", is not found in the system config JSON file.");
        return false;
    }

    types::ObjectMap l_objectInterfaceMap;
    for (const auto& l_Fru : m_parsedJson["frus"][i_vpdFilePath])
    {
        types::InterfaceMap l_interfaces;
        sdbusplus::message::object_path l_fruObjectPath(l_Fru["inventoryPath"]);

        if (l_Fru.contains("ccin"))
        {
            continue;
        }

        if (l_Fru.contains("noprime") && l_Fru.value("noprime", false))
        {
            continue;
        }

        // Reset data under PIM for this FRU only if the FRU is not synthesized
        // and we handle it's Present property.
        if (isPresentPropertyHandlingRequired(l_Fru))
        {
            // Clear data under PIM if already exists.
            vpdSpecificUtility::resetDataUnderPIM(
                std::string(l_Fru["inventoryPath"]), l_interfaces);
        }

        // Add extra interfaces mentioned in the Json config file
        if (l_Fru.contains("extraInterfaces"))
        {
            populateInterfaces(l_Fru["extraInterfaces"], l_interfaces,
                               std::monostate{});
        }

        types::PropertyMap l_propertyValueMap;

        // Update Present property for this FRU only if we handle Present
        // property for the FRU.
        if (isPresentPropertyHandlingRequired(l_Fru))
        {
            l_propertyValueMap.emplace("Present", false);

            // TODO: Present based on file will be taken care in future.
            // By default present is set to false for FRU at the time of
            // priming. Once collection goes through, it will be set to true in
            // that flow.
            /*if (std::filesystem::exists(i_vpdFilePath))
            {
                l_propertyValueMap["Present"] = true;
            }*/
        }

        vpdSpecificUtility::insertOrMerge(l_interfaces,
                                          "xyz.openbmc_project.Inventory.Item",
                                          move(l_propertyValueMap));

        if (l_Fru.value("inherit", true) &&
            m_parsedJson.contains("commonInterfaces"))
        {
            populateInterfaces(m_parsedJson["commonInterfaces"], l_interfaces,
                               std::monostate{});
        }

        processFunctionalProperty(l_Fru["inventoryPath"], l_interfaces);
        processEnabledProperty(l_Fru["inventoryPath"], l_interfaces);

        // Emplace the default state of FRU VPD collection
        types::PropertyMap l_fruCollectionProperty = {
            {"CollectionStatus", constants::vpdCollectionNotStarted}};

        vpdSpecificUtility::insertOrMerge(l_interfaces,
                                          constants::vpdCollectionInterface,
                                          std::move(l_fruCollectionProperty));

        l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
                                     std::move(l_interfaces));
    }

    // Notify PIM
    if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
    {
        logging::logMessage("Call to PIM failed for VPD file " + i_vpdFilePath);
        return false;
    }

    return true;
}

void Worker::processEmbeddedAndSynthesizedFrus(const nlohmann::json& singleFru,
                                               types::InterfaceMap& interfaces)
{
    // embedded property(true or false) says whether the subfru is embedded
    // into the parent fru (or) not. VPD sets Present property only for
    // embedded frus. If the subfru is not an embedded FRU, the subfru may
    // or may not be physically present. Those non embedded frus will always
    // have Present=false irrespective of its physical presence or absence.
    // Eg: nvme drive in nvme slot is not an embedded FRU. So don't set
    // Present to true for such sub frus.
    // Eg: ethernet port is embedded into bmc card. So set Present to true
    // for such sub frus. Also donot populate present property for embedded
    // subfru which is synthesized. Currently there is no subfru which are
    // both embedded and synthesized. But still the case is handled here.

    // Check if its required to handle presence for this FRU.
    if (singleFru.value("handlePresence", true))
    {
        types::PropertyMap presProp;
        presProp.emplace("Present", true);
        vpdSpecificUtility::insertOrMerge(
            interfaces, "xyz.openbmc_project.Inventory.Item", move(presProp));
    }
}

void Worker::processExtraInterfaces(const nlohmann::json& singleFru,
                                    types::InterfaceMap& interfaces,
                                    const types::VPDMapVariant& parsedVpdMap)
{
    populateInterfaces(singleFru["extraInterfaces"], interfaces, parsedVpdMap);
    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        if (singleFru["extraInterfaces"].contains(
                "xyz.openbmc_project.Inventory.Item.Cpu"))
        {
            auto itrToRec = (*ipzVpdMap).find("CP00");
            if (itrToRec == (*ipzVpdMap).end())
            {
                return;
            }

            const std::string pgKeywordValue{
                vpdSpecificUtility::getKwVal(itrToRec->second, "PG")};

            if (!pgKeywordValue.empty())
            {
                if (isCPUIOGoodOnly(pgKeywordValue))
                {
                    interfaces["xyz.openbmc_project.Inventory.Item"]
                              ["PrettyName"] = "IO Module";
                }
            }
            else
            {
                throw DataException(std::string(__FUNCTION__) +
                                    "Failed to get value for keyword PG");
            }
        }
    }
}

void Worker::processCopyRecordFlag(const nlohmann::json& singleFru,
                                   const types::VPDMapVariant& parsedVpdMap,
                                   types::InterfaceMap& interfaces)
{
    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        for (const auto& record : singleFru["copyRecords"])
        {
            const std::string& recordName = record;
            if ((*ipzVpdMap).find(recordName) != (*ipzVpdMap).end())
            {
                populateIPZVPDpropertyMap(interfaces,
                                          (*ipzVpdMap).at(recordName),
                                          constants::ipzVpdInf + recordName);
            }
        }
    }
}

void Worker::processInheritFlag(const types::VPDMapVariant& parsedVpdMap,
                                types::InterfaceMap& interfaces)
{
    if (auto ipzVpdMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        for (const auto& [recordName, kwdValueMap] : *ipzVpdMap)
        {
            populateIPZVPDpropertyMap(interfaces, kwdValueMap,
                                      constants::ipzVpdInf + recordName);
        }
    }
    else if (auto kwdVpdMap = std::get_if<types::KeywordVpdMap>(&parsedVpdMap))
    {
        populateKwdVPDpropertyMap(*kwdVpdMap, interfaces);
    }

    if (m_parsedJson.contains("commonInterfaces"))
    {
        populateInterfaces(m_parsedJson["commonInterfaces"], interfaces,
                           parsedVpdMap);
    }
}

bool Worker::processFruWithCCIN(const nlohmann::json& singleFru,
                                const types::VPDMapVariant& parsedVpdMap)
{
    if (auto ipzVPDMap = std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        auto itrToRec = (*ipzVPDMap).find("VINI");
        if (itrToRec == (*ipzVPDMap).end())
        {
            return false;
        }

        std::string ccinFromVpd{
            vpdSpecificUtility::getKwVal(itrToRec->second, "CC")};

        if (ccinFromVpd.empty())
        {
            return false;
        }

        transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
                  ::toupper);

        std::vector<std::string> ccinList;
        for (std::string ccin : singleFru["ccin"])
        {
            transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
            ccinList.push_back(ccin);
        }

        if (ccinList.empty())
        {
            return false;
        }

        if (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
            ccinList.end())
        {
            return false;
        }
    }
    return true;
}

void Worker::processFunctionalProperty(const std::string& i_inventoryObjPath,
                                       types::InterfaceMap& io_interfaces)
{
    if (!dbusUtility::isChassisPowerOn())
    {
        std::array<const char*, 1> l_operationalStatusInf = {
            constants::operationalStatusInf};

        auto mapperObjectMap = dbusUtility::getObjectMap(
            i_inventoryObjPath, l_operationalStatusInf);

        // If the object has been found. Check if it is under PIM.
        if (mapperObjectMap.size() != 0)
        {
            for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
            {
                if (l_serviceName == constants::pimServiceName)
                {
                    // The object is already under PIM. No need to process
                    // again. Retain the old value.
                    return;
                }
            }
        }

        // Implies value is not there in D-Bus. Populate it with default
        // value "true".
        types::PropertyMap l_functionalProp;
        l_functionalProp.emplace("Functional", true);
        vpdSpecificUtility::insertOrMerge(io_interfaces,
                                          constants::operationalStatusInf,
                                          move(l_functionalProp));
    }

    // if chassis is power on. Functional property should be there on D-Bus.
    // Don't process.
    return;
}

void Worker::processEnabledProperty(const std::string& i_inventoryObjPath,
                                    types::InterfaceMap& io_interfaces)
{
    if (!dbusUtility::isChassisPowerOn())
    {
        std::array<const char*, 1> l_enableInf = {constants::enableInf};

        auto mapperObjectMap =
            dbusUtility::getObjectMap(i_inventoryObjPath, l_enableInf);

        // If the object has been found. Check if it is under PIM.
        if (mapperObjectMap.size() != 0)
        {
            for (const auto& [l_serviceName, l_interfaceLsit] : mapperObjectMap)
            {
                if (l_serviceName == constants::pimServiceName)
                {
                    // The object is already under PIM. No need to process
                    // again. Retain the old value.
                    return;
                }
            }
        }

        // Implies value is not there in D-Bus. Populate it with default
        // value "true".
        types::PropertyMap l_enabledProp;
        l_enabledProp.emplace("Enabled", true);
        vpdSpecificUtility::insertOrMerge(io_interfaces, constants::enableInf,
                                          move(l_enabledProp));
    }

    // if chassis is power on. Enabled property should be there on D-Bus.
    // Don't process.
    return;
}

void Worker::populateDbus(const types::VPDMapVariant& parsedVpdMap,
                          types::ObjectMap& objectInterfaceMap,
                          const std::string& vpdFilePath)
{
    if (vpdFilePath.empty())
    {
        throw std::runtime_error(
            std::string(__FUNCTION__) +
            "Invalid parameter passed to populateDbus API.");
    }

    // JSON config is mandatory for processing of "if". Add "else" for any
    // processing without config JSON.
    if (!m_parsedJson.empty())
    {
        types::InterfaceMap interfaces;

        for (const auto& aFru : m_parsedJson["frus"][vpdFilePath])
        {
            const auto& inventoryPath = aFru["inventoryPath"];
            sdbusplus::message::object_path fruObjectPath(inventoryPath);
            if (aFru.contains("ccin"))
            {
                if (!processFruWithCCIN(aFru, parsedVpdMap))
                {
                    continue;
                }
            }

            if (aFru.value("inherit", true))
            {
                processInheritFlag(parsedVpdMap, interfaces);
            }

            // If specific record needs to be copied.
            if (aFru.contains("copyRecords"))
            {
                processCopyRecordFlag(aFru, parsedVpdMap, interfaces);
            }

            if (aFru.contains("extraInterfaces"))
            {
                // Process extra interfaces w.r.t a FRU.
                processExtraInterfaces(aFru, interfaces, parsedVpdMap);
            }

            // Process FRUS which are embedded in the parent FRU and whose VPD
            // will be synthesized.
            if ((aFru.value("embedded", true)) &&
                (!aFru.value("synthesized", false)))
            {
                processEmbeddedAndSynthesizedFrus(aFru, interfaces);
            }

            processFunctionalProperty(inventoryPath, interfaces);
            processEnabledProperty(inventoryPath, interfaces);

            // Update collection status as successful
            types::PropertyMap l_collectionProperty = {
                {"CollectionStatus", constants::vpdCollectionSuccess}};

            vpdSpecificUtility::insertOrMerge(interfaces,
                                              constants::vpdCollectionInterface,
                                              std::move(l_collectionProperty));

            objectInterfaceMap.emplace(std::move(fruObjectPath),
                                       std::move(interfaces));
        }
    }
}

std::string Worker::createAssetTagString(
    const types::VPDMapVariant& i_parsedVpdMap)
{
    std::string l_assetTag;

    // system VPD will be in IPZ format.
    if (auto l_parsedVpdMap = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
    {
        auto l_itrToVsys = (*l_parsedVpdMap).find(constants::recVSYS);
        if (l_itrToVsys != (*l_parsedVpdMap).end())
        {
            const std::string l_tmKwdValue{vpdSpecificUtility::getKwVal(
                l_itrToVsys->second, constants::kwdTM)};

            if (l_tmKwdValue.empty())
            {
                throw std::runtime_error(
                    std::string("Failed to get value for keyword [") +
                    constants::kwdTM +
                    std::string("] while creating Asset tag."));
            }

            const std::string l_seKwdValue{vpdSpecificUtility::getKwVal(
                l_itrToVsys->second, constants::kwdSE)};

            if (l_seKwdValue.empty())
            {
                throw std::runtime_error(
                    std::string("Failed to get value for keyword [") +
                    constants::kwdSE +
                    std::string("] while creating Asset tag."));
            }

            l_assetTag = std::string{"Server-"} + l_tmKwdValue +
                         std::string{"-"} + l_seKwdValue;
        }
        else
        {
            throw std::runtime_error(
                "VSYS record not found in parsed VPD map to create Asset tag.");
        }
    }
    else
    {
        throw std::runtime_error(
            "Invalid VPD type recieved to create Asset tag.");
    }

    return l_assetTag;
}

void Worker::publishSystemVPD(const types::VPDMapVariant& parsedVpdMap)
{
    types::ObjectMap objectInterfaceMap;

    if (std::get_if<types::IPZVpdMap>(&parsedVpdMap))
    {
        populateDbus(parsedVpdMap, objectInterfaceMap, SYSTEM_VPD_FILE_PATH);

        try
        {
            if (m_isFactoryResetDone)
            {
                const auto& l_assetTag = createAssetTagString(parsedVpdMap);

                auto l_itrToSystemPath = objectInterfaceMap.find(
                    sdbusplus::message::object_path(constants::systemInvPath));
                if (l_itrToSystemPath == objectInterfaceMap.end())
                {
                    throw std::runtime_error(
                        "Asset tag update failed. System Path not found in object map.");
                }

                types::PropertyMap l_assetTagProperty;
                l_assetTagProperty.emplace("AssetTag", l_assetTag);

                (l_itrToSystemPath->second)
                    .emplace(constants::assetTagInf,
                             std::move(l_assetTagProperty));
            }
        }
        catch (const std::exception& l_ex)
        {
            EventLogger::createSyncPel(
                EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
                __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
        }

        // Notify PIM
        if (!dbusUtility::callPIM(move(objectInterfaceMap)))
        {
            throw std::runtime_error("Call to PIM failed for system VPD");
        }
    }
    else
    {
        throw DataException("Invalid format of parsed VPD map.");
    }
}

bool Worker::processPreAction(const std::string& i_vpdFilePath,
                              const std::string& i_flagToProcess)
{
    if (i_vpdFilePath.empty() || i_flagToProcess.empty())
    {
        logging::logMessage(
            "Invalid input parameter. Abort processing pre action");
        return false;
    }

    if ((!jsonUtility::executeBaseAction(m_parsedJson, "preAction",
                                         i_vpdFilePath, i_flagToProcess)) &&
        (i_flagToProcess.compare("collection") == constants::STR_CMP_SUCCESS))
    {
        // TODO: Need a way to delete inventory object from Dbus and persisted
        // data section in case any FRU is not present or there is any
        // problem in collecting it. Once it has been deleted, it can be
        // re-created in the flow of priming the inventory. This needs to be
        // done either here or in the exception section of "parseAndPublishVPD"
        // API. Any failure in the process of collecting FRU will land up in the
        // excpetion of "parseAndPublishVPD".

        // If the FRU is not there, clear the VINI/CCIN data.
        // Enity manager probes for this keyword to look for this
        // FRU, now if the data is persistent on BMC and FRU is
        // removed this can lead to ambiguity. Hence clearing this
        // Keyword if FRU is absent.
        const auto& inventoryPath =
            m_parsedJson["frus"][i_vpdFilePath].at(0).value("inventoryPath",
                                                            "");

        if (!inventoryPath.empty())
        {
            types::ObjectMap l_pimObjMap{
                {inventoryPath,
                 {{constants::kwdVpdInf,
                   {{constants::kwdCCIN, types::BinaryVector{}}}}}}};

            if (!dbusUtility::callPIM(std::move(l_pimObjMap)))
            {
                logging::logMessage(
                    "Call to PIM failed for file " + i_vpdFilePath);
            }
        }
        else
        {
            logging::logMessage(
                "Inventory path is empty in Json for file " + i_vpdFilePath);
        }

        return false;
    }
    return true;
}

bool Worker::processPostAction(
    const std::string& i_vpdFruPath, const std::string& i_flagToProcess,
    const std::optional<types::VPDMapVariant> i_parsedVpd)
{
    if (i_vpdFruPath.empty() || i_flagToProcess.empty())
    {
        logging::logMessage(
            "Invalid input parameter. Abort processing post action");
        return false;
    }

    // Check if post action tag is to be triggered in the flow of collection
    // based on some CCIN value?
    if (m_parsedJson["frus"][i_vpdFruPath]
            .at(0)["postAction"][i_flagToProcess]
            .contains("ccin"))
    {
        if (!i_parsedVpd.has_value())
        {
            logging::logMessage("Empty VPD Map");
            return false;
        }

        // CCIN match is required to process post action for this FRU as it
        // contains the flag.
        if (!vpdSpecificUtility::findCcinInVpd(
                m_parsedJson["frus"][i_vpdFruPath].at(
                    0)["postAction"]["collection"],
                i_parsedVpd.value()))
        {
            // If CCIN is not found, implies post action processing is not
            // required for this FRU. Let the flow continue.
            return true;
        }
    }

    if (!jsonUtility::executeBaseAction(m_parsedJson, "postAction",
                                        i_vpdFruPath, i_flagToProcess))
    {
        logging::logMessage(
            "Execution of post action failed for path: " + i_vpdFruPath);

        // If post action was required and failed only in that case return
        // false. In all other case post action is considered passed.
        return false;
    }

    return true;
}

types::VPDMapVariant Worker::parseVpdFile(const std::string& i_vpdFilePath)
{
    try
    {
        if (i_vpdFilePath.empty())
        {
            throw std::runtime_error(
                std::string(__FUNCTION__) +
                " Empty VPD file path passed. Abort processing");
        }

        bool isPreActionRequired = false;
        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
                                          "preAction", "collection"))
        {
            isPreActionRequired = true;
            if (!processPreAction(i_vpdFilePath, "collection"))
            {
                throw std::runtime_error(
                    std::string(__FUNCTION__) + " Pre-Action failed");
            }
        }

        if (!std::filesystem::exists(i_vpdFilePath))
        {
            if (isPreActionRequired)
            {
                throw std::runtime_error(
                    std::string(__FUNCTION__) + " Could not find file path " +
                    i_vpdFilePath + "Skipping parser trigger for the EEPROM");
            }
            return types::VPDMapVariant{};
        }

        std::shared_ptr<Parser> vpdParser =
            std::make_shared<Parser>(i_vpdFilePath, m_parsedJson);

        types::VPDMapVariant l_parsedVpd = vpdParser->parse();

        // Before returning, as collection is over, check if FRU qualifies for
        // any post action in the flow of collection.
        // Note: Don't change the order, post action needs to be processed only
        // after collection for FRU is successfully done.
        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
                                          "postAction", "collection"))
        {
            if (!processPostAction(i_vpdFilePath, "collection", l_parsedVpd))
            {
                // Post action was required but failed while executing.
                // Behaviour can be undefined.
                EventLogger::createSyncPel(
                    types::ErrorType::InternalFailure,
                    types::SeverityType::Warning, __FILE__, __FUNCTION__, 0,
                    std::string("Required post action failed for path [" +
                                i_vpdFilePath + "]"),
                    std::nullopt, std::nullopt, std::nullopt, std::nullopt);
            }
        }

        return l_parsedVpd;
    }
    catch (std::exception& l_ex)
    {
        std::string l_exMsg{
            std::string(__FUNCTION__) + " : VPD parsing failed for " +
            i_vpdFilePath + " due to error: " + l_ex.what()};

        // If post fail action is required, execute it.
        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
                                          "postFailAction", "collection"))
        {
            if (!jsonUtility::executePostFailAction(m_parsedJson, i_vpdFilePath,
                                                    "collection"))
            {
                l_exMsg +=
                    ". Post Fail Action also failed, aborting collection for this FRU";
            }
        }

        if (typeid(l_ex) == typeid(DataException))
        {
            throw DataException(l_exMsg);
        }
        else if (typeid(l_ex) == typeid(EccException))
        {
            throw EccException(l_exMsg);
        }
        throw std::runtime_error(l_exMsg);
    }
}

std::tuple<bool, std::string> Worker::parseAndPublishVPD(
    const std::string& i_vpdFilePath)
{
    std::string l_inventoryPath{};

    try
    {
        m_semaphore.acquire();

        // Thread launched.
        m_mutex.lock();
        m_activeCollectionThreadCount++;
        m_mutex.unlock();

        // Set CollectionStatus as InProgress. Since it's an intermediate state
        // D-bus set-property call is good enough to update the status.
        l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
            m_parsedJson, i_vpdFilePath);

        if (!l_inventoryPath.empty())
        {
            if (!dbusUtility::writeDbusProperty(
                    jsonUtility::getServiceName(m_parsedJson, l_inventoryPath),
                    l_inventoryPath, constants::vpdCollectionInterface,
                    "CollectionStatus",
                    types::DbusVariantType{constants::vpdCollectionInProgress}))
            {
                logging::logMessage(
                    "Unable to set CollectionStatus as InProgress for " +
                    i_vpdFilePath + ". Error : " + "DBus write failed");
            }
        }

        const types::VPDMapVariant& parsedVpdMap = parseVpdFile(i_vpdFilePath);
        if (!std::holds_alternative<std::monostate>(parsedVpdMap))
        {
            types::ObjectMap objectInterfaceMap;
            populateDbus(parsedVpdMap, objectInterfaceMap, i_vpdFilePath);

            // Notify PIM
            if (!dbusUtility::callPIM(move(objectInterfaceMap)))
            {
                throw std::runtime_error(
                    std::string(__FUNCTION__) +
                    "Call to PIM failed while publishing VPD.");
            }
        }
        else
        {
            logging::logMessage("Empty parsedVpdMap recieved for path [" +
                                i_vpdFilePath + "]. Check PEL for reason.");
        }
    }
    catch (const std::exception& ex)
    {
        setCollectionStatusProperty(i_vpdFilePath,
                                    constants::vpdCollectionFailure);

        // handle all the exceptions internally. Return only true/false
        // based on status of execution.
        if (typeid(ex) == std::type_index(typeid(DataException)))
        {
            // In case of pass1 planar, VPD can be corrupted on PCIe cards. Skip
            // logging error for these cases.
            if (vpdSpecificUtility::isPass1Planar())
            {
                const std::string& l_invPathLeafValue =
                    sdbusplus::message::object_path(
                        jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
                                                                 i_vpdFilePath))
                        .filename();

                if ((l_invPathLeafValue.find("pcie_card", 0) !=
                     std::string::npos))
                {
                    // skip logging any PEL for PCIe cards on pass 1 planar.
                    return std::make_tuple(false, i_vpdFilePath);
                }
            }
        }

        EventLogger::createSyncPel(
            EventLogger::getErrorType(ex),
            (typeid(ex) == typeid(DataException)) ||
                    (typeid(ex) == typeid(EccException))
                ? types::SeverityType::Warning
                : types::SeverityType::Informational,
            __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(ex),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);

        // TODO: Figure out a way to clear data in case of any failure at
        // runtime.

        // set present property to false for any error case. In future this will
        // be replaced by presence logic.
        // Update Present property for this FRU only if we handle Present
        // property for the FRU.
        if (isPresentPropertyHandlingRequired(
                m_parsedJson["frus"][i_vpdFilePath].at(0)))
        {
            setPresentProperty(i_vpdFilePath, false);
        }

        m_semaphore.release();
        return std::make_tuple(false, i_vpdFilePath);
    }
    m_semaphore.release();
    return std::make_tuple(true, i_vpdFilePath);
}

bool Worker::skipPathForCollection(const std::string& i_vpdFilePath)
{
    if (i_vpdFilePath.empty())
    {
        return true;
    }

    // skip processing of system VPD again as it has been already collected.
    if (i_vpdFilePath == SYSTEM_VPD_FILE_PATH)
    {
        return true;
    }

    if (dbusUtility::isChassisPowerOn())
    {
        // If chassis is powered on, skip collecting FRUs which are
        // powerOffOnly.
        if (jsonUtility::isFruPowerOffOnly(m_parsedJson, i_vpdFilePath))
        {
            return true;
        }

        const std::string& l_invPathLeafValue =
            sdbusplus::message::object_path(
                jsonUtility::getInventoryObjPathFromJson(m_parsedJson,
                                                         i_vpdFilePath))
                .filename();

        if ((l_invPathLeafValue.find("pcie_card", 0) != std::string::npos))
        {
            return true;
        }
    }

    return false;
}

void Worker::collectFrusFromJson()
{
    // A parsed JSON file should be present to pick FRUs EEPROM paths
    if (m_parsedJson.empty())
    {
        throw JsonException(
            std::string(__FUNCTION__) +
                ": Config JSON is mandatory for processing of FRUs through this API.",
            m_configJsonPath);
    }

    const nlohmann::json& listOfFrus =
        m_parsedJson["frus"].get_ref<const nlohmann::json::object_t&>();

    for (const auto& itemFRUS : listOfFrus.items())
    {
        const std::string& vpdFilePath = itemFRUS.key();

        if (skipPathForCollection(vpdFilePath))
        {
            continue;
        }

        try
        {
            std::thread{[vpdFilePath, this]() {
                const auto& l_parseResult = parseAndPublishVPD(vpdFilePath);

                m_mutex.lock();
                m_activeCollectionThreadCount--;
                m_mutex.unlock();

                if (!m_activeCollectionThreadCount)
                {
                    m_isAllFruCollected = true;
                }
            }}.detach();
        }
        catch (const std::exception& l_ex)
        {
            // add vpdFilePath(EEPROM path) to failed list
            m_failedEepromPaths.push_front(vpdFilePath);
        }
    }
}

// ToDo: Move the API under IBM_SYSTEM
void Worker::performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap)
{
    try
    {
        std::string l_backupAndRestoreCfgFilePath =
            m_parsedJson.value("backupRestoreConfigPath", "");

        nlohmann::json l_backupAndRestoreCfgJsonObj =
            jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath);

        if (l_backupAndRestoreCfgJsonObj.empty())
        {
            throw JsonException("JSON parsing failed",
                                l_backupAndRestoreCfgFilePath);
        }

        // check if either of "source" or "destination" has inventory path.
        // this indicates that this sytem has System VPD on hardware
        // and other copy on D-Bus (BMC cache).
        if (!l_backupAndRestoreCfgJsonObj.empty() &&
            ((l_backupAndRestoreCfgJsonObj.contains("source") &&
              l_backupAndRestoreCfgJsonObj["source"].contains(
                  "inventoryPath")) ||
             (l_backupAndRestoreCfgJsonObj.contains("destination") &&
              l_backupAndRestoreCfgJsonObj["destination"].contains(
                  "inventoryPath"))))
        {
            BackupAndRestore l_backupAndRestoreObj(m_parsedJson);
            auto [l_srcVpdVariant,
                  l_dstVpdVariant] = l_backupAndRestoreObj.backupAndRestore();

            // ToDo: Revisit is this check is required or not.
            if (auto l_srcVpdMap =
                    std::get_if<types::IPZVpdMap>(&l_srcVpdVariant);
                l_srcVpdMap && !(*l_srcVpdMap).empty())
            {
                io_srcVpdMap = std::move(l_srcVpdVariant);
            }
        }
    }
    catch (const std::exception& l_ex)
    {
        EventLogger::createSyncPel(
            EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
            __FILE__, __FUNCTION__, 0,
            std::string(
                "Exception caught while backup and restore VPD keyword's.") +
                EventLogger::getErrorMsg(l_ex),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }
}

void Worker::deleteFruVpd(const std::string& i_dbusObjPath)
{
    if (i_dbusObjPath.empty())
    {
        throw std::runtime_error("Given DBus object path is empty.");
    }

    const std::string& l_fruPath =
        jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath);

    try
    {
        auto l_presentPropValue = dbusUtility::readDbusProperty(
            constants::pimServiceName, i_dbusObjPath,
            constants::inventoryItemInf, "Present");

        if (auto l_value = std::get_if<bool>(&l_presentPropValue))
        {
            // check if FRU's Present property is handled by vpd-manager
            const auto& l_isFruPresenceHandled =
                jsonUtility::isFruPresenceHandled(m_parsedJson, l_fruPath);

            if (!(*l_value) && l_isFruPresenceHandled)
            {
                throw std::runtime_error("Given FRU is not present");
            }
            else if (*l_value && !l_isFruPresenceHandled)
            {
                throw std::runtime_error(
                    "Given FRU is present and its presence is not handled by vpd-manager.");
            }
            else
            {
                if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
                                                  "preAction", "deletion"))
                {
                    if (!processPreAction(l_fruPath, "deletion"))
                    {
                        throw std::runtime_error("Pre action failed");
                    }
                }

                std::vector<std::string> l_interfaceList{
                    constants::operationalStatusInf};

                types::MapperGetSubTree l_subTreeMap =
                    dbusUtility::getObjectSubTree(i_dbusObjPath, 0,
                                                  l_interfaceList);

                types::ObjectMap l_objectMap;

                // Updates VPD specific interfaces property value under PIM for
                // sub FRUs.
                for (const auto& [l_objectPath, l_serviceInterfaceMap] :
                     l_subTreeMap)
                {
                    types::InterfaceMap l_interfaceMap;
                    vpdSpecificUtility::resetDataUnderPIM(l_objectPath,
                                                          l_interfaceMap);
                    l_objectMap.emplace(l_objectPath,
                                        std::move(l_interfaceMap));
                }

                types::InterfaceMap l_interfaceMap;
                vpdSpecificUtility::resetDataUnderPIM(i_dbusObjPath,
                                                      l_interfaceMap);

                l_objectMap.emplace(i_dbusObjPath, std::move(l_interfaceMap));

                if (!dbusUtility::callPIM(std::move(l_objectMap)))
                {
                    throw std::runtime_error("Call to PIM failed.");
                }

                if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
                                                  "postAction", "deletion"))
                {
                    if (!processPostAction(l_fruPath, "deletion"))
                    {
                        throw std::runtime_error("Post action failed");
                    }
                }
            }
        }
        else
        {
            logging::logMessage(
                "Can't process delete VPD for FRU [" + i_dbusObjPath +
                "] as unable to read present property");
            return;
        }

        logging::logMessage(
            "Successfully completed deletion of FRU VPD for " + i_dbusObjPath);
    }
    catch (const std::exception& l_ex)
    {
        if (jsonUtility::isActionRequired(m_parsedJson, l_fruPath,
                                          "postFailAction", "deletion"))
        {
            if (!jsonUtility::executePostFailAction(m_parsedJson, l_fruPath,
                                                    "deletion"))
            {
                logging::logMessage(
                    "Post fail action failed for: " + i_dbusObjPath);
            }
        }

        logging::logMessage("Failed to delete VPD for FRU : " + i_dbusObjPath +
                            " error: " + std::string(l_ex.what()));
    }
}

void Worker::setPresentProperty(const std::string& i_vpdPath,
                                const bool& i_value)
{
    try
    {
        if (i_vpdPath.empty())
        {
            throw std::runtime_error(
                "Path is empty. Can't set present property");
        }

        types::ObjectMap l_objectInterfaceMap;

        // If the given path is EEPROM path.
        if (m_parsedJson["frus"].contains(i_vpdPath))
        {
            for (const auto& l_Fru : m_parsedJson["frus"][i_vpdPath])
            {
                sdbusplus::message::object_path l_fruObjectPath(
                    l_Fru["inventoryPath"]);

                types::PropertyMap l_propertyValueMap;
                l_propertyValueMap.emplace("Present", i_value);

                types::InterfaceMap l_interfaces;
                vpdSpecificUtility::insertOrMerge(l_interfaces,
                                                  constants::inventoryItemInf,
                                                  move(l_propertyValueMap));

                l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
                                             std::move(l_interfaces));
            }
        }
        else
        {
            // consider it as an inventory path.
            if (i_vpdPath.find(constants::pimPath) != constants::VALUE_0)
            {
                throw std::runtime_error(
                    "Invalid inventory path: " + i_vpdPath);
            }

            types::PropertyMap l_propertyValueMap;
            l_propertyValueMap.emplace("Present", i_value);

            types::InterfaceMap l_interfaces;
            vpdSpecificUtility::insertOrMerge(l_interfaces,
                                              constants::inventoryItemInf,
                                              move(l_propertyValueMap));

            l_objectInterfaceMap.emplace(i_vpdPath, std::move(l_interfaces));
        }

        // Notify PIM
        if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
        {
            throw DbusException(
                std::string(__FUNCTION__) +
                "Call to PIM failed while setting present property for path " +
                i_vpdPath);
        }
    }
    catch (const std::exception& l_ex)
    {
        EventLogger::createSyncPel(
            EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
            __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }
}

void Worker::performVpdRecollection()
{
    try
    {
        // Check if system config JSON is present
        if (m_parsedJson.empty())
        {
            throw std::runtime_error(
                "System config json object is empty, can't process recollection.");
        }

        const auto& l_frusReplaceableAtStandby =
            jsonUtility::getListOfFrusReplaceableAtStandby(m_parsedJson);

        for (const auto& l_fruInventoryPath : l_frusReplaceableAtStandby)
        {
            // ToDo: Add some logic/trace to know the flow to
            // collectSingleFruVpd has been directed via
            // performVpdRecollection.
            collectSingleFruVpd(l_fruInventoryPath);
        }
        return;
    }

    catch (const std::exception& l_ex)
    {
        // TODO Log PEL
        logging::logMessage(
            "VPD recollection failed with error: " + std::string(l_ex.what()));
    }
}

void Worker::collectSingleFruVpd(
    const sdbusplus::message::object_path& i_dbusObjPath)
{
    try
    {
        // Check if system config JSON is present
        if (m_parsedJson.empty())
        {
            logging::logMessage(
                "System config JSON object not present. Single FRU VPD collection is not performed for " +
                std::string(i_dbusObjPath));
            return;
        }

        // Get FRU path for the given D-bus object path from JSON
        const std::string& l_fruPath =
            jsonUtility::getFruPathFromJson(m_parsedJson, i_dbusObjPath);

        if (l_fruPath.empty())
        {
            logging::logMessage(
                "D-bus object path not present in JSON. Single FRU VPD collection is not performed for " +
                std::string(i_dbusObjPath));
            return;
        }

        // Check if host is up and running
        if (dbusUtility::isHostRunning())
        {
            if (!jsonUtility::isFruReplaceableAtRuntime(m_parsedJson,
                                                        l_fruPath))
            {
                logging::logMessage(
                    "Given FRU is not replaceable at host runtime. Single FRU VPD collection is not performed for " +
                    std::string(i_dbusObjPath));
                return;
            }
        }
        else if (dbusUtility::isBMCReady())
        {
            if (!jsonUtility::isFruReplaceableAtStandby(m_parsedJson,
                                                        l_fruPath) &&
                (!jsonUtility::isFruReplaceableAtRuntime(m_parsedJson,
                                                         l_fruPath)))
            {
                logging::logMessage(
                    "Given FRU is neither replaceable at standby nor replaceable at runtime. Single FRU VPD collection is not performed for " +
                    std::string(i_dbusObjPath));
                return;
            }
        }

        // Set CollectionStatus as InProgress. Since it's an intermediate state
        // D-bus set-property call is good enough to update the status.
        const std::string& l_collStatusProp = "CollectionStatus";

        if (!dbusUtility::writeDbusProperty(
                jsonUtility::getServiceName(m_parsedJson,
                                            std::string(i_dbusObjPath)),
                std::string(i_dbusObjPath), constants::vpdCollectionInterface,
                l_collStatusProp,
                types::DbusVariantType{constants::vpdCollectionInProgress}))
        {
            logging::logMessage(
                "Unable to set CollectionStatus as InProgress for " +
                std::string(i_dbusObjPath) +
                ". Continue single FRU VPD collection.");
        }

        // Parse VPD
        types::VPDMapVariant l_parsedVpd = parseVpdFile(l_fruPath);

        // If l_parsedVpd is pointing to std::monostate
        if (l_parsedVpd.index() == 0)
        {
            throw std::runtime_error(
                "VPD parsing failed for " + std::string(i_dbusObjPath));
        }

        // Get D-bus object map from worker class
        types::ObjectMap l_dbusObjectMap;
        populateDbus(l_parsedVpd, l_dbusObjectMap, l_fruPath);

        if (l_dbusObjectMap.empty())
        {
            throw std::runtime_error(
                "Failed to create D-bus object map. Single FRU VPD collection failed for " +
                std::string(i_dbusObjPath));
        }

        // Call PIM's Notify method
        if (!dbusUtility::callPIM(move(l_dbusObjectMap)))
        {
            throw std::runtime_error(
                "Notify PIM failed. Single FRU VPD collection failed for " +
                std::string(i_dbusObjPath));
        }
    }
    catch (const std::exception& l_error)
    {
        // Notify FRU's VPD CollectionStatus as Failure
        if (!dbusUtility::notifyFRUCollectionStatus(
                std::string(i_dbusObjPath), constants::vpdCollectionFailure))
        {
            logging::logMessage(
                "Call to PIM Notify method failed to update Collection status as Failure for " +
                std::string(i_dbusObjPath));
        }

        // TODO: Log PEL
        logging::logMessage(std::string(l_error.what()));
    }
}

void Worker::setCollectionStatusProperty(
    const std::string& i_vpdPath, const std::string& i_value) const noexcept
{
    try
    {
        if (i_vpdPath.empty())
        {
            throw std::runtime_error(
                "Given path is empty. Can't set CollectionStatus property");
        }

        types::ObjectMap l_objectInterfaceMap;

        if (m_parsedJson["frus"].contains(i_vpdPath))
        {
            for (const auto& l_Fru : m_parsedJson["frus"][i_vpdPath])
            {
                sdbusplus::message::object_path l_fruObjectPath(
                    l_Fru["inventoryPath"]);

                types::PropertyMap l_propertyValueMap;
                l_propertyValueMap.emplace("CollectionStatus", i_value);

                types::InterfaceMap l_interfaces;
                vpdSpecificUtility::insertOrMerge(
                    l_interfaces, constants::vpdCollectionInterface,
                    move(l_propertyValueMap));

                l_objectInterfaceMap.emplace(std::move(l_fruObjectPath),
                                             std::move(l_interfaces));
            }
        }
        else
        {
            // consider it as an inventory path.
            if (i_vpdPath.find(constants::pimPath) != constants::VALUE_0)
            {
                throw std::runtime_error(
                    "Invalid inventory path: " + i_vpdPath +
                    ". Can't set CollectionStatus property");
            }

            types::PropertyMap l_propertyValueMap;
            l_propertyValueMap.emplace("CollectionStatus", i_value);

            types::InterfaceMap l_interfaces;
            vpdSpecificUtility::insertOrMerge(l_interfaces,
                                              constants::vpdCollectionInterface,
                                              move(l_propertyValueMap));

            l_objectInterfaceMap.emplace(i_vpdPath, std::move(l_interfaces));
        }

        // Notify PIM
        if (!dbusUtility::callPIM(move(l_objectInterfaceMap)))
        {
            throw DbusException(
                std::string(__FUNCTION__) +
                "Call to PIM failed while setting CollectionStatus property for path " +
                i_vpdPath);
        }
    }
    catch (const std::exception& l_ex)
    {
        EventLogger::createSyncPel(
            EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
            __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
            std::nullopt, std::nullopt, std::nullopt, std::nullopt);
    }
}
} // namespace vpd
