#include "config.h"

#include "manager.hpp"

#include "common_utility.hpp"
#include "editor_impl.hpp"
#include "ibm_vpd_utils.hpp"
#include "ipz_parser.hpp"
#include "parser_factory.hpp"
#include "reader_impl.hpp"
#include "vpd_exceptions.hpp"

#include <unistd.h>

#include <phosphor-logging/elog-errors.hpp>
#include <xyz/openbmc_project/Common/error.hpp>

#include <filesystem>

using namespace openpower::vpd::constants;
using namespace openpower::vpd::inventory;
using namespace openpower::vpd::manager::editor;
using namespace openpower::vpd::manager::reader;
using namespace std;
using namespace openpower::vpd::parser;
using namespace openpower::vpd::parser::factory;
using namespace openpower::vpd::ipz::parser;
using namespace openpower::vpd::exceptions;
using namespace phosphor::logging;

namespace openpower
{
namespace vpd
{
namespace manager
{

Manager::Manager(std::shared_ptr<boost::asio::io_context>& ioCon,
                 std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
                 std::shared_ptr<sdbusplus::asio::connection>& conn) :
    ioContext(ioCon), interface(iFace), conn(conn)
{
    interface->register_method(
        "WriteKeyword",
        [this](const sdbusplus::message::object_path& path,
               const std::string& recordName, const std::string& keyword,
               const Binary& value) {
            this->writeKeyword(path, recordName, keyword, value);
        });

    interface->register_method(
        "GetFRUsByUnexpandedLocationCode",
        [this](const std::string& locationCode,
               const uint16_t nodeNumber) -> inventory::ListOfPaths {
            return this->getFRUsByUnexpandedLocationCode(locationCode,
                                                         nodeNumber);
        });

    interface->register_method(
        "GetFRUsByExpandedLocationCode",
        [this](const std::string& locationCode) -> inventory::ListOfPaths {
            return this->getFRUsByExpandedLocationCode(locationCode);
        });

    interface->register_method(
        "GetExpandedLocationCode",
        [this](const std::string& locationCode,
               const uint16_t nodeNumber) -> std::string {
            return this->getExpandedLocationCode(locationCode, nodeNumber);
        });

    interface->register_method("PerformVPDRecollection", [this]() {
        this->performVPDRecollection();
    });

    interface->register_method(
        "deleteFRUVPD", [this](const sdbusplus::message::object_path& path) {
            this->deleteFRUVPD(path);
        });

    interface->register_method(
        "CollectFRUVPD", [this](const sdbusplus::message::object_path& path) {
            this->collectFRUVPD(path);
        });

    sd_bus_default(&sdBus);
    initManager();
}

void Manager::initManager()
{
    try
    {
        processJSON();
        restoreSystemVpd();
        listenHostState();
        listenAssetTag();

        // Create an instance of the BIOS handler
        biosHandler = std::make_shared<BiosHandler>(conn, *this);

        // instantiate gpioMonitor class
        gpioMon = std::make_shared<GpioMonitor>(jsonFile, ioContext);
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << "\n";
    }
}

/**
 * @brief An api to get list of blank system VPD properties.
 * @param[in] vpdMap - IPZ vpd map.
 * @param[in] objectPath - Object path for the FRU.
 * @param[out] blankPropertyList - Properties which are blank in System VPD and
 * needs to be updated as standby.
 */
static void
    getListOfBlankSystemVpd(Parsed& vpdMap, const string& objectPath,
                            std::vector<RestoredEeproms>& blankPropertyList)
{
    for (const auto& systemRecKwdPair : svpdKwdMap)
    {
        auto it = vpdMap.find(systemRecKwdPair.first);

        // check if record is found in map we got by parser
        if (it != vpdMap.end())
        {
            const auto& kwdListForRecord = systemRecKwdPair.second;
            for (const auto& keywordInfo : kwdListForRecord)
            {
                const auto& keyword = get<0>(keywordInfo);

                DbusPropertyMap& kwdValMap = it->second;
                auto iterator = kwdValMap.find(keyword);

                if (iterator != kwdValMap.end())
                {
                    string& kwdValue = iterator->second;

                    // check bus data
                    const string& recordName = systemRecKwdPair.first;
                    const string& busValue = readBusProperty(
                        objectPath, ipzVpdInf + recordName, keyword);

                    const auto& defaultValue = get<1>(keywordInfo);

                    if (Binary(busValue.begin(), busValue.end()) !=
                        defaultValue)
                    {
                        if (Binary(kwdValue.begin(), kwdValue.end()) ==
                            defaultValue)
                        {
                            // implies data is blank on EEPROM but not on cache.
                            // So EEPROM vpd update is required.
                            Binary busData(busValue.begin(), busValue.end());

                            blankPropertyList.push_back(std::make_tuple(
                                objectPath, recordName, keyword, busData));
                        }
                    }
                }
            }
        }
    }
}

void Manager::restoreSystemVpd()
{
    std::cout << "Attempting system VPD restore" << std::endl;
    ParserInterface* parser = nullptr;
    try
    {
        auto vpdVector = getVpdDataInVector(jsonFile, systemVpdFilePath);
        uint32_t vpdStartOffset = 0;
        const auto& inventoryPath =
            jsonFile["frus"][systemVpdFilePath][0]["inventoryPath"]
                .get_ref<const nlohmann::json::string_t&>();

        parser = ParserFactory::getParser(vpdVector, (pimPath + inventoryPath),
                                          systemVpdFilePath, vpdStartOffset);
        auto parseResult = parser->parse();

        if (auto pVal = std::get_if<Store>(&parseResult))
        {
            // map to hold all the keywords whose value is blank and
            // needs to be updated at standby.
            std::vector<RestoredEeproms> blankSystemVpdProperties{};
            getListOfBlankSystemVpd(pVal->getVpdMap(), SYSTEM_OBJECT,
                                    blankSystemVpdProperties);

            // if system VPD restore is required, update the
            // EEPROM
            for (const auto& item : blankSystemVpdProperties)
            {
                std::cout << "Restoring keyword: " << std::get<2>(item)
                          << std::endl;
                writeKeyword(std::get<0>(item), std::get<1>(item),
                             std::get<2>(item), std::get<3>(item));
            }
        }
        else
        {
            std::cerr << "Not a valid format to restore system VPD"
                      << std::endl;
        }
    }
    catch (const std::exception& e)
    {
        std::cerr << "Failed to restore system VPD due to exception: "
                  << e.what() << std::endl;
    }
    // release the parser object
    ParserFactory::freeParser(parser);
}

void Manager::listenHostState()
{
    static std::shared_ptr<sdbusplus::bus::match_t> hostState =
        std::make_shared<sdbusplus::bus::match_t>(
            *conn,
            sdbusplus::bus::match::rules::propertiesChanged(
                "/xyz/openbmc_project/state/host0",
                "xyz.openbmc_project.State.Host"),
            [this](sdbusplus::message_t& msg) { hostStateCallBack(msg); });
}

void Manager::checkEssentialFrus()
{
    for (const auto& invPath : essentialFrus)
    {
        const auto res = readBusProperty(invPath, invItemIntf, "Present");

        // implies the essential FRU is missing. Log PEL.
        if (res == "false")
        {
            auto rc = sd_bus_call_method_async(
                sdBus, NULL, loggerService, loggerObjectPath,
                loggerCreateInterface, "Create", NULL, NULL, "ssa{ss}",
                errIntfForEssentialFru,
                "xyz.openbmc_project.Logging.Entry.Level.Warning", 2,
                "DESCRIPTION", "Essential fru missing from the system.",
                "CALLOUT_INVENTORY_PATH", (pimPath + invPath).c_str());

            if (rc < 0)
            {
                log<level::ERR>("Error calling sd_bus_call_method_async",
                                entry("RC=%d", rc),
                                entry("MSG=%s", strerror(-rc)));
            }
        }
    }
}

void Manager::hostStateCallBack(sdbusplus::message_t& msg)
{
    if (msg.is_method_error())
    {
        std::cerr << "Error in reading signal " << std::endl;
    }

    Path object;
    PropertyMap propMap;
    msg.read(object, propMap);
    const auto itr = propMap.find("CurrentHostState");
    if (itr != propMap.end())
    {
        if (auto hostState = std::get_if<std::string>(&(itr->second)))
        {
            // implies system is moving from standby to power on state
            if (*hostState == "xyz.openbmc_project.State.Host.HostState."
                              "TransitioningToRunning")
            {
                // detect if essential frus are present in the system.
                checkEssentialFrus();

                // check and perform recollection for FRUs replaceable at
                // standby.
                performVPDRecollection();
                return;
            }
        }
    }
}

void Manager::listenAssetTag()
{
    static std::shared_ptr<sdbusplus::bus::match_t> assetMatcher =
        std::make_shared<sdbusplus::bus::match_t>(
            *conn,
            sdbusplus::bus::match::rules::propertiesChanged(
                "/xyz/openbmc_project/inventory/system",
                "xyz.openbmc_project.Inventory.Decorator.AssetTag"),
            [this](sdbusplus::message_t& msg) { assetTagCallback(msg); });
}

void Manager::assetTagCallback(sdbusplus::message_t& msg)
{
    if (msg.is_method_error())
    {
        std::cerr << "Error in reading signal " << std::endl;
    }

    Path object;
    PropertyMap propMap;
    msg.read(object, propMap);
    const auto itr = propMap.find("AssetTag");
    if (itr != propMap.end())
    {
        if (auto assetTag = std::get_if<std::string>(&(itr->second)))
        {
            // Call Notify to persist the AssetTag
            inventory::ObjectMap objectMap = {
                {std::string{"/system"},
                 {{"xyz.openbmc_project.Inventory.Decorator.AssetTag",
                   {{"AssetTag", *assetTag}}}}}};

            common::utility::callPIM(std::move(objectMap));
        }
        else
        {
            std::cerr << "Failed to read asset tag" << std::endl;
        }
    }
}

void Manager::processJSON()
{
    std::ifstream json(INVENTORY_JSON_SYM_LINK, std::ios::binary);

    if (!json)
    {
        throw std::runtime_error("json file not found");
    }

    jsonFile = nlohmann::json::parse(json);
    if (jsonFile.find("frus") == jsonFile.end())
    {
        throw std::runtime_error("frus group not found in json");
    }

    const nlohmann::json& groupFRUS =
        jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
    for (const auto& itemFRUS : groupFRUS.items())
    {
        const std::vector<nlohmann::json>& groupEEPROM =
            itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
        for (const auto& itemEEPROM : groupEEPROM)
        {
            bool isMotherboard = false;
            std::string redundantPath;

            if (itemEEPROM["extraInterfaces"].find(
                    "xyz.openbmc_project.Inventory.Item.Board.Motherboard") !=
                itemEEPROM["extraInterfaces"].end())
            {
                isMotherboard = true;
            }
            if (itemEEPROM.find("redundantEeprom") != itemEEPROM.end())
            {
                redundantPath = itemEEPROM["redundantEeprom"]
                                    .get_ref<const nlohmann::json::string_t&>();
            }
            frus.emplace(
                itemEEPROM["inventoryPath"]
                    .get_ref<const nlohmann::json::string_t&>(),
                std::make_tuple(itemFRUS.key(), redundantPath, isMotherboard));

            if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
                itemEEPROM["extraInterfaces"].end())
            {
                fruLocationCode.emplace(
                    itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
                              ["LocationCode"]
                                  .get_ref<const nlohmann::json::string_t&>(),
                    itemEEPROM["inventoryPath"]
                        .get_ref<const nlohmann::json::string_t&>());
            }

            if (itemEEPROM.value("replaceableAtStandby", false))
            {
                replaceableFrus.emplace_back(itemFRUS.key());
            }

            if (itemEEPROM.value("essentialFru", false))
            {
                essentialFrus.emplace_back(itemEEPROM["inventoryPath"]);
            }
        }
    }
}

void Manager::updateSystemVPDBackUpFRU(const std::string& recordName,
                                       const std::string& keyword,
                                       const Binary& value)
{
    const std::string& systemVpdBackupPath =
        jsonFile["frus"][systemVpdFilePath].at(0).value("systemVpdBackupPath",
                                                        "");

    if (!systemVpdBackupPath.empty() &&
        jsonFile["frus"][systemVpdBackupPath].at(0).contains("inventoryPath"))
    {
        std::string systemVpdBackupInvPath =
            jsonFile["frus"][systemVpdBackupPath][0]["inventoryPath"]
                .get_ref<const nlohmann::json::string_t&>();

        const auto& itr = svpdKwdMap.find(recordName);
        if (itr != svpdKwdMap.end())
        {
            auto systemKwdInfoList = itr->second;
            const auto& itrToKwd =
                find_if(systemKwdInfoList.begin(), systemKwdInfoList.end(),
                        [&keyword](const auto& kwdInfo) {
                            return (keyword == std::get<0>(kwdInfo));
                        });

            if (itrToKwd != systemKwdInfoList.end())
            {
                EditorImpl edit(systemVpdBackupPath, jsonFile,
                                std::get<4>(*itrToKwd), std::get<5>(*itrToKwd),
                                systemVpdBackupInvPath);

                // Setup offset, if any
                uint32_t offset = 0;
                if (jsonFile["frus"][systemVpdBackupPath].at(0).contains(
                        "offset"))
                {
                    offset =
                        jsonFile["frus"][systemVpdBackupPath].at(0).contains(
                            "offset");
                }

                edit.updateKeyword(value, offset, true);
            }
        }
    }
    else
    {
        if (systemVpdBackupPath.empty())
        {
            throw std::runtime_error(
                "Invalid entry for systemVpdBackupPath in JSON");
        }
        else
        {
            throw std::runtime_error(
                "Inventory path missing for systemVpdBackupPath");
        }
    }
}

void Manager::writeKeyword(const sdbusplus::message::object_path& path,
                           const std::string& recordName,
                           const std::string& keyword, const Binary& value)
{
    try
    {
        std::string objPath{path};
        // Strip any inventory prefix in path
        if (objPath.find(INVENTORY_PATH) == 0)
        {
            objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
        }

        if (frus.find(objPath) == frus.end())
        {
            throw std::runtime_error("Inventory path not found");
        }

        inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);

        // instantiate editor class to update the data
        EditorImpl edit(vpdFilePath, jsonFile, recordName, keyword, objPath);

        uint32_t offset = 0;
        // Setup offset, if any
        for (const auto& item : jsonFile["frus"][vpdFilePath])
        {
            if (item.find("offset") != item.end())
            {
                offset = item["offset"];
                break;
            }
        }

        edit.updateKeyword(value, offset, true);

        // If system VPD is being updated and system VPD is marked for back up
        // on another FRU, update data on back up as well.
        if (objPath == sdbusplus::message::object_path{SYSTEM_OBJECT} &&
            jsonFile["frus"][systemVpdFilePath].at(0).contains(
                "systemVpdBackupPath"))
        {
            updateSystemVPDBackUpFRU(recordName, keyword, value);
        }

        // If we have a redundant EEPROM to update, then update just the EEPROM,
        // not the cache since that is already done when we updated the primary
        if (!std::get<1>(frus.find(objPath)->second).empty())
        {
            EditorImpl edit(std::get<1>(frus.find(objPath)->second), jsonFile,
                            recordName, keyword, objPath);
            edit.updateKeyword(value, offset, false);
        }

        // if it is a motehrboard FRU need to check for location expansion
        if (std::get<2>(frus.find(objPath)->second))
        {
            if (recordName == "VCEN" && (keyword == "FC" || keyword == "SE"))
            {
                edit.expandLocationCode("fcs");
            }
            else if (recordName == "VSYS" &&
                     (keyword == "TM" || keyword == "SE"))
            {
                edit.expandLocationCode("mts");
            }
        }

        return;
    }
    catch (const std::exception& e)
    {
        std::cerr << e.what() << std::endl;
    }
}

ListOfPaths Manager::getFRUsByUnexpandedLocationCode(
    const LocationCode& locationCode, const NodeNumber nodeNumber)
{
    ReaderImpl read;
    return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
}

ListOfPaths
    Manager::getFRUsByExpandedLocationCode(const LocationCode& locationCode)
{
    ReaderImpl read;
    return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
}

LocationCode Manager::getExpandedLocationCode(const LocationCode& locationCode,
                                              const NodeNumber nodeNumber)
{
    ReaderImpl read;
    return read.getExpandedLocationCode(locationCode, nodeNumber,
                                        fruLocationCode);
}

void Manager::performVPDRecollection()
{
    // get list of FRUs replaceable at standby
    for (const auto& item : replaceableFrus)
    {
        const vector<nlohmann::json>& groupEEPROM = jsonFile["frus"][item];
        const nlohmann::json& singleFru = groupEEPROM[0];

        const string& inventoryPath =
            singleFru["inventoryPath"]
                .get_ref<const nlohmann::json::string_t&>();

        bool prePostActionRequired = false;

        if ((jsonFile["frus"][item].at(0)).find("preAction") !=
            jsonFile["frus"][item].at(0).end())
        {
            try
            {
                if (!executePreAction(jsonFile, item))
                {
                    // if the FRU has preAction defined then its execution
                    // should pass to ensure bind/unbind of data.
                    // preAction execution failed. should not call
                    // bind/unbind.
                    log<level::ERR>(
                        "Pre-Action execution failed for the FRU",
                        entry("ERROR=%s",
                              ("Inventory path: " + inventoryPath).c_str()));
                    continue;
                }
            }
            catch (const GpioException& e)
            {
                log<level::ERR>(e.what());
                PelAdditionalData additionalData{};
                additionalData.emplace("DESCRIPTION", e.what());
                createPEL(additionalData, PelSeverity::WARNING,
                          errIntfForGpioError, sdBus);
                continue;
            }
            prePostActionRequired = true;
        }

        // unbind, bind the driver to trigger parser.
        triggerVpdCollection(singleFru, inventoryPath);

        // this check is added to avoid file system expensive call in case not
        // required.
        if (prePostActionRequired)
        {
            // The sleep of 1sec is sliced up in 10 retries of 10 milliseconds
            // each.
            for (auto retryCounter = VALUE_0; retryCounter <= VALUE_10;
                 retryCounter++)
            {
                // sleep for 10 millisecond
                if (usleep(VALUE_100000) != VALUE_0)
                {
                    std::cout << "Sleep failed before accessing the file"
                              << std::endl;
                }

                // Check if file showed up
                if (!filesystem::exists(item))
                {
                    // Do we need to retry?
                    if (retryCounter < VALUE_10)
                    {
                        continue;
                    }

                    try
                    {
                        // If not, then take failure postAction
                        executePostFailAction(jsonFile, item);
                    }
                    catch (const GpioException& e)
                    {
                        PelAdditionalData additionalData{};
                        additionalData.emplace("DESCRIPTION", e.what());
                        createPEL(additionalData, PelSeverity::WARNING,
                                  errIntfForGpioError, sdBus);
                    }
                }
                else
                {
                    // bind the LED driver
                    string chipAddr = singleFru.value("pcaChipAddress", "");
                    cout
                        << "performVPDRecollection: Executing driver binding for "
                           "chip "
                           "address - "
                        << chipAddr << endl;

                    executeCmd(createBindUnbindDriverCmnd(
                        chipAddr, "i2c", "leds-pca955x", "/bind"));

                    // File has been found, kill the retry loop.
                    break;
                }
            }
        }
    }
}

void Manager::collectFRUVPD(const sdbusplus::message::object_path& path)
{
    std::cout << "Manager called to collect vpd for fru: " << std::string{path}
              << std::endl;

    using InvalidArgument =
        sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
    using Argument = xyz::openbmc_project::Common::InvalidArgument;

    std::string objPath{path};

    // Strip any inventory prefix in path
    if (objPath.find(INVENTORY_PATH) == 0)
    {
        objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
    }

    // if path not found in Json.
    if (frus.find(objPath) == frus.end())
    {
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
                              Argument::ARGUMENT_VALUE(objPath.c_str()));
    }

    inventory::Path vpdFilePath = std::get<0>(frus.find(objPath)->second);

    const std::vector<nlohmann::json>& groupEEPROM =
        jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();

    nlohmann::json singleFru{};
    for (const auto& item : groupEEPROM)
    {
        if (item["inventoryPath"] == objPath)
        {
            // this is the inventory we are looking for
            singleFru = item;
            break;
        }
    }

    // check if the device qualifies for CM.
    if (singleFru.value("concurrentlyMaintainable", false))
    {
        bool prePostActionRequired = false;

        if ((jsonFile["frus"][vpdFilePath].at(0)).find("preAction") !=
            jsonFile["frus"][vpdFilePath].at(0).end())
        {
            if (!executePreAction(jsonFile, vpdFilePath))
            {
                // if the FRU has preAction defined then its execution should
                // pass to ensure bind/unbind of data.
                // preAction execution failed. should not call bind/unbind.
                log<level::ERR>("Pre-Action execution failed for the FRU");
                return;
            }

            prePostActionRequired = true;
        }

        // unbind, bind the driver to trigger parser.
        triggerVpdCollection(singleFru, objPath);

        // this check is added to avoid file system expensive call in case not
        // required.
        if (prePostActionRequired)
        {
            // Check if device showed up (test for file)
            if (!filesystem::exists(vpdFilePath))
            {
                try
                {
                    // If not, then take failure postAction
                    executePostFailAction(jsonFile, vpdFilePath);
                }
                catch (const GpioException& e)
                {
                    PelAdditionalData additionalData{};
                    additionalData.emplace("DESCRIPTION", e.what());
                    createPEL(additionalData, PelSeverity::WARNING,
                              errIntfForGpioError, sdBus);
                }
            }
            else
            {
                // bind the LED driver
                string chipAddr = jsonFile["frus"][vpdFilePath].at(0).value(
                    "pcaChipAddress", "");
                cout << "Executing driver binding for chip address - "
                     << chipAddr << endl;

                executeCmd(createBindUnbindDriverCmnd(chipAddr, "i2c",
                                                      "leds-pca955x", "/bind"));
            }
        }
        return;
    }
    else
    {
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
                              Argument::ARGUMENT_VALUE(objPath.c_str()));
    }
}

void Manager::triggerVpdCollection(const nlohmann::json& singleFru,
                                   const std::string& path)
{
    if ((singleFru.find("devAddress") == singleFru.end()) ||
        (singleFru.find("driverType") == singleFru.end()) ||
        (singleFru.find("busType") == singleFru.end()))
    {
        // The FRUs is marked for collection but missing mandatory
        // fields for collection. Log error and return.
        log<level::ERR>(
            "Collection Failed as mandatory field missing in Json",
            entry("ERROR=%s", ("Recollection failed for " + (path)).c_str()));

        return;
    }

    string deviceAddress = singleFru["devAddress"];
    const string& driverType = singleFru["driverType"];
    const string& busType = singleFru["busType"];

    // devTreeStatus flag is present in json as false to mention
    // that the EEPROM is not mentioned in device tree. If this flag
    // is absent consider the value to be true, i.e EEPROM is
    // mentioned in device tree
    if (!singleFru.value("devTreeStatus", true))
    {
        auto pos = deviceAddress.find('-');
        if (pos != string::npos)
        {
            string busNum = deviceAddress.substr(0, pos);
            deviceAddress = "0x" + deviceAddress.substr(pos + 1, string::npos);

            string deleteDevice =
                "echo" + deviceAddress + " > /sys/bus/" + busType +
                "/devices/" + busType + "-" + busNum + "/delete_device";
            executeCmd(deleteDevice);

            string addDevice =
                "echo" + driverType + " " + deviceAddress + " > /sys/bus/" +
                busType + "/devices/" + busType + "-" + busNum + "/new_device";
            executeCmd(addDevice);
        }
        else
        {
            const string& inventoryPath =
                singleFru["inventoryPath"]
                    .get_ref<const nlohmann::json::string_t&>();

            log<level::ERR>(
                "Wrong format of device address in Json",
                entry("ERROR=%s",
                      ("Recollection failed for " + inventoryPath).c_str()));
        }
    }
    else
    {
        executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
                                              driverType, "/unbind"));
        executeCmd(createBindUnbindDriverCmnd(deviceAddress, busType,
                                              driverType, "/bind"));
    }
}

void Manager::deleteFRUVPD(const sdbusplus::message::object_path& path)
{
    std::cout << "Manager called to delete vpd for fru: " << std::string{path}
              << std::endl;

    using InvalidArgument =
        sdbusplus::xyz::openbmc_project::Common::Error::InvalidArgument;
    using Argument = xyz::openbmc_project::Common::InvalidArgument;

    std::string objPath{path};

    // Strip any inventory prefix in path
    if (objPath.find(INVENTORY_PATH) == 0)
    {
        objPath = objPath.substr(sizeof(INVENTORY_PATH) - 1);
    }

    // if path not found in Json.
    if (frus.find(objPath) == frus.end())
    {
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("Object Path"),
                              Argument::ARGUMENT_VALUE(objPath.c_str()));
    }

    inventory::Path& vpdFilePath = std::get<0>(frus.find(objPath)->second);

    string chipAddress =
        jsonFile["frus"][vpdFilePath].at(0).value("pcaChipAddress", "");

    // if the FRU is not present then log error
    if (readBusProperty(objPath, "xyz.openbmc_project.Inventory.Item",
                        "Present") == "false")
    {
        elog<InvalidArgument>(Argument::ARGUMENT_NAME("FRU not preset"),
                              Argument::ARGUMENT_VALUE(objPath.c_str()));
    }
    else
    {
        // check if we have cxp-port populated for the given object path.
        std::vector<std::string> interfaceList{
            "xyz.openbmc_project.State.Decorator.OperationalStatus"};
        MapperResponse subTree =
            getObjectSubtreeForInterfaces(path, 0, interfaceList);

        if (subTree.size() != 0)
        {
            for (auto [objectPath, serviceInterfaceMap] : subTree)
            {
                std::string subTreeObjPath{objectPath};
                if (subTreeObjPath.find("cxp_top") != std::string::npos ||
                    subTreeObjPath.find("cxp_bot") != std::string::npos)
                {
                    // Strip any inventory prefix in path
                    if (subTreeObjPath.find(INVENTORY_PATH) == 0)
                    {
                        subTreeObjPath =
                            subTreeObjPath.substr(sizeof(INVENTORY_PATH) - 1);
                    }

                    inventory::ObjectMap objectMap{
                        {subTreeObjPath,
                         {{"xyz.openbmc_project.State.Decorator.OperationalStatus",
                           {{"Functional", true}}}}}};

                    // objectMap.emplace(objectPath, move(interfaceMap));
                    common::utility::callPIM(move(objectMap));
                }
            }
        }

        // Unbind the LED driver for this FRU
        cout << "Unbinding device- " << chipAddress << endl;
        executeCmd(createBindUnbindDriverCmnd(chipAddress, "i2c",
                                              "leds-pca955x", "/unbind"));

        inventory::InterfaceMap interfacesPropMap;
        clearVpdOnRemoval(INVENTORY_PATH + objPath, interfacesPropMap);

        inventory::ObjectMap objectMap;
        objectMap.emplace(objPath, move(interfacesPropMap));

        common::utility::callPIM(move(objectMap));
    }
}

} // namespace manager
} // namespace vpd
} // namespace openpower
