#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");
    }
}

void Worker::enableMuxChips()
{
    if (m_parsedJson.empty())
    {
        // config JSON should not be empty at this point of execution.
        throw std::runtime_error("Config JSON is empty. Can't enable muxes");
        return;
    }

    if (!m_parsedJson.contains("muxes"))
    {
        logging::logMessage("No mux defined for the system in config JSON");
        return;
    }

    // iterate over each MUX detail and enable them.
    for (const auto& item : m_parsedJson["muxes"])
    {
        if (item.contains("holdidlepath"))
        {
            std::string cmd = "echo 0 > ";
            cmd += item["holdidlepath"];

            logging::logMessage("Enabling mux with command = " + cmd);

            commonUtility::executeCmd(cmd);
            continue;
        }

        logging::logMessage(
            "Mux Entry does not have hold idle path. Can't enable the mux");
    }
}

#ifdef IBM_SYSTEM
void Worker::primeSystemBlueprint()
{
    if (m_parsedJson.empty())
    {
        return;
    }

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

    for (const auto& l_itemFRUS : l_listOfFrus.items())
    {
        const std::string& l_vpdFilePath = l_itemFRUS.key();

        if (l_vpdFilePath == SYSTEM_VPD_FILE_PATH)
        {
            continue;
        }

        // Prime the inventry for FRUs which
        // are not present/processing had some error.
        if (!primeInventory(l_vpdFilePath))
        {
            logging::logMessage(
                "Priming of inventory failed for FRU " + l_vpdFilePath);
        }
    }
}

void Worker::performInitialSetup()
{
    try
    {
        if (!dbusUtility::isChassisPowerOn())
        {
            logging::logMessage("Chassis is in Off state.");
            setDeviceTreeAndJson();
            primeSystemBlueprint();
        }

        // Enable all mux which are used for connecting to the i2c on the
        // pcie slots for pcie cards. These are not enabled by kernel due to
        // an issue seen with Castello cards, where the i2c line hangs on a
        // probe.
        enableMuxChips();

        // Nothing needs to be done. Service restarted or BMC re-booted for
        // some reason at system power on.
        return;
    }
    catch (const std::exception& ex)
    {
        if (typeid(ex) == std::type_index(typeid(DataException)))
        {
            // TODO:Catch logic to be implemented once PEL code goes in.
        }
        else if (typeid(ex) == std::type_index(typeid(EccException)))
        {
            // TODO:Catch logic to be implemented once PEL code goes in.
        }
        else if (typeid(ex) == std::type_index(typeid(JsonException)))
        {
            // TODO:Catch logic to be implemented once PEL code goes in.
        }

        logging::logMessage(ex.what());
        throw;
    }
}
#endif

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");
    }

    try
    {
        std::shared_ptr<Parser> vpdParser =
            std::make_shared<Parser>(vpdFilePath, m_parsedJson);
        vpdMap = vpdParser->parse();
    }
    catch (const std::exception& ex)
    {
        if (typeid(ex) == std::type_index(typeid(DataException)))
        {
            // TODO: Do what needs to be done in case of Data exception.
            // Uncomment when PEL implementation goes in.
            /* string errorMsg =
                 "VPD file is either empty or invalid. Parser failed for [";
             errorMsg += m_vpdFilePath;
             errorMsg += "], with error = " + std::string(ex.what());

             additionalData.emplace("DESCRIPTION", errorMsg);
             additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                    INVENTORY_PATH + baseFruInventoryPath);
             createPEL(additionalData, pelSeverity, errIntfForInvalidVPD,
             nullptr);*/

            // throw generic error from here to inform main caller about
            // failure.
            logging::logMessage(ex.what());
            throw std::runtime_error(
                "Data Exception occurred for file path = " + vpdFilePath);
        }

        if (typeid(ex) == std::type_index(typeid(EccException)))
        {
            // TODO: Do what needs to be done in case of ECC exception.
            // Uncomment when PEL implementation goes in.
            /* additionalData.emplace("DESCRIPTION", "ECC check failed");
             additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                    INVENTORY_PATH + baseFruInventoryPath);
             createPEL(additionalData, pelSeverity, errIntfForEccCheckFail,
                       nullptr);
             */

            logging::logMessage(ex.what());
            // Need to decide once all error handling is implemented.
            // vpdSpecificUtility::dumpBadVpd(vpdFilePath,vpdVector);

            // throw generic error from here to inform main caller about
            // failure.
            throw std::runtime_error(
                "Ecc Exception occurred for file path = " + vpdFilePath);
        }
    }
}

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");
}

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();
    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 std::runtime_error("JSON is empty");
    }

    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.

    // Do we have the entry for device tree in parsed JSON?
    if (m_parsedJson.find("devTree") == m_parsedJson.end())
    {
        getSystemJson(systemJson, parsedVpdMap);

        if (!systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
        {
            // TODO: Log a PEL saying that "System type not supported"
            throw DataException("Error in getting system JSON.");
        }

        // 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())
        {
            // TODO:: Log a predictive PEL
            logging::logMessage(
                "Mandatory value for device tree missing from JSON[" +
                std::string(INVENTORY_JSON_SYM_LINK) + "]");
        }
    }

    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.

        // avoid setting symlink on every reboot.
        if (!m_isSymlinkPresent)
        {
            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;
            }

            std::string pgKeywordValue;
            vpdSpecificUtility::getKwVal(itrToRec->second, "PG",
                                         pgKeywordValue);
            if (!pgKeywordValue.empty())
            {
                if (isCPUIOGoodOnly(pgKeywordValue))
                {
                    interfaces["xyz.openbmc_project.Inventory.Item"]
                              ["PrettyName"] = "IO Module";
                }
            }
        }
    }
}

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", ccinFromVpd);
        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(
            "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())
        {
            std::string l_tmKwdValue;
            vpdSpecificUtility::getKwVal(l_itrToVsys->second, constants::kwdTM,
                                         l_tmKwdValue);

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

            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(
                        "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(
                types::ErrorType::InvalidVpdMessage,
                types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
                "Asset tag update failed with following error: " +
                    std::string(l_ex.what()),
                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)
{
    if (i_vpdFilePath.empty())
    {
        throw std::runtime_error(
            "Empty VPD file path passed to Worker::parseVpdFile. Abort processing");
    }

    try
    {
        if (jsonUtility::isActionRequired(m_parsedJson, i_vpdFilePath,
                                          "preAction", "collection"))
        {
            if (!processPreAction(i_vpdFilePath, "collection"))
            {
                throw std::runtime_error("Pre-Action failed");
            }
        }

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

        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))
            {
                // TODO: Log PEL
                logging::logMessage("Required post action failed for path [" +
                                    i_vpdFilePath + "]");
            }
        }

        return l_parsedVpd;
    }
    catch (std::exception& l_ex)
    {
        // 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"))
            {
                // TODO: Log PEL
                throw std::runtime_error(
                    "VPD parsing failed for " + i_vpdFilePath +
                    " due to error: " + l_ex.what() +
                    ". Post Fail Action also failed, aborting collection for this FRU");
            }
        }

        // TODO: Log PEL
        throw std::runtime_error("VPD parsing failed for " + i_vpdFilePath +
                                 " due to error: " + l_ex.what());
    }
}

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);

        types::ObjectMap objectInterfaceMap;
        populateDbus(parsedVpdMap, objectInterfaceMap, i_vpdFilePath);

        // logging::logMessage("Dbus sucessfully populated for FRU " +
        //                     i_vpdFilePath);

        // Notify PIM
        if (!dbusUtility::callPIM(move(objectInterfaceMap)))
        {
            throw std::runtime_error(
                "Call to PIM failed while publishing VPD.");
        }
    }
    catch (const std::exception& ex)
    {
        // Notify FRU's VPD CollectionStatus as Failure
        if (!dbusUtility::notifyFRUCollectionStatus(
                l_inventoryPath, constants::vpdCollectionFailure))
        {
            logging::logMessage(
                "Call to PIM Notify method failed to update Collection status as Failure for " +
                i_vpdFilePath);
        }

        // 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);
                }
            }

            // TODO: Add custom handling
            logging::logMessage(ex.what());
        }
        else if (typeid(ex) == std::type_index(typeid(EccException)))
        {
            // TODO: Add custom handling
            logging::logMessage(ex.what());
        }
        else if (typeid(ex) == std::type_index(typeid(JsonException)))
        {
            // TODO: Add custom handling
            logging::logMessage(ex.what());
        }
        else
        {
            logging::logMessage(ex.what());
        }

        // 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 std::runtime_error(
            "A config JSON is required for processing of FRUs");
    }

    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(
            types::ErrorType::InvalidVpdMessage,
            types::SeverityType::Informational, __FILE__, __FUNCTION__, 0,
            std::string(
                "Exception caught while backup and restore VPD keyword's.") +
                l_ex.what(),
            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))
        {
            if (!(*l_value))
            {
                throw std::runtime_error("Given FRU is not present");
            }
            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 std::runtime_error(
                "Call to PIM failed while setting present property for path " +
                i_vpdPath);
        }
    }
    catch (const std::exception& l_ex)
    {
        logging::logMessage(l_ex.what());
    }
}

} // namespace vpd
