#include "config.h"

#include "common_utility.hpp"
#include "defines.hpp"
#include "ibm_vpd_utils.hpp"
#include "ipz_parser.hpp"
#include "keyword_vpd_parser.hpp"
#include "memory_vpd_parser.hpp"
#include "parser_factory.hpp"
#include "vpd_exceptions.hpp"

#include <assert.h>
#include <ctype.h>

#include <CLI/CLI.hpp>
#include <algorithm>
#include <boost/algorithm/string.hpp>
#include <cstdarg>
#include <exception>
#include <filesystem>
#include <fstream>
#include <gpiod.hpp>
#include <iostream>
#include <iterator>
#include <nlohmann/json.hpp>
#include <phosphor-logging/log.hpp>
#include <regex>

using namespace std;
using namespace openpower::vpd;
using namespace CLI;
using namespace vpd::keyword::parser;
using namespace openpower::vpd::constants;
namespace fs = filesystem;
using json = nlohmann::json;
using namespace openpower::vpd::parser::factory;
using namespace openpower::vpd::inventory;
using namespace openpower::vpd::memory::parser;
using namespace openpower::vpd::parser::interface;
using namespace openpower::vpd::exceptions;
using namespace phosphor::logging;

// Map to hold record, kwd pair which can be re-stored at standby.
// The list of keywords for VSYS record is as per the S0 system. Should
// be updated for another type of systems
static const std::unordered_map<std::string, std::vector<std::string>>
    svpdKwdMap{{"VSYS", {"BR", "TM", "SE", "SU", "RB"}},
               {"VCEN", {"FC", "SE"}},
               {"LXR0", {"LX"}}};

/**
 * @brief Returns the power state for chassis0
 */
static auto getPowerState()
{
    // TODO: How do we handle multiple chassis?
    string powerState{};
    auto bus = sdbusplus::bus::new_default();
    auto properties =
        bus.new_method_call("xyz.openbmc_project.State.Chassis",
                            "/xyz/openbmc_project/state/chassis0",
                            "org.freedesktop.DBus.Properties", "Get");
    properties.append("xyz.openbmc_project.State.Chassis");
    properties.append("CurrentPowerState");
    auto result = bus.call(properties);
    if (!result.is_method_error())
    {
        variant<string> val;
        result.read(val);
        if (auto pVal = get_if<string>(&val))
        {
            powerState = *pVal;
        }
    }
    cout << "Power state is: " << powerState << endl;
    return powerState;
}

/**
 * @brief Expands location codes
 */
static auto expandLocationCode(const string& unexpanded, const Parsed& vpdMap,
                               bool isSystemVpd)
{
    auto expanded{unexpanded};
    static constexpr auto SYSTEM_OBJECT = "/system/chassis/motherboard";
    static constexpr auto VCEN_IF = "com.ibm.ipzvpd.VCEN";
    static constexpr auto VSYS_IF = "com.ibm.ipzvpd.VSYS";
    size_t idx = expanded.find("fcs");
    try
    {
        if (idx != string::npos)
        {
            string fc{};
            string se{};
            if (isSystemVpd)
            {
                const auto& fcData = vpdMap.at("VCEN").at("FC");
                const auto& seData = vpdMap.at("VCEN").at("SE");
                fc = string(fcData.data(), fcData.size());
                se = string(seData.data(), seData.size());
            }
            else
            {
                fc = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "FC");
                se = readBusProperty(SYSTEM_OBJECT, VCEN_IF, "SE");
            }

            // TODO: See if ND0 can be placed in the JSON
            expanded.replace(idx, 3, fc.substr(0, 4) + ".ND0." + se);
        }
        else
        {
            idx = expanded.find("mts");
            if (idx != string::npos)
            {
                string mt{};
                string se{};
                if (isSystemVpd)
                {
                    const auto& mtData = vpdMap.at("VSYS").at("TM");
                    const auto& seData = vpdMap.at("VSYS").at("SE");
                    mt = string(mtData.data(), mtData.size());
                    se = string(seData.data(), seData.size());
                }
                else
                {
                    mt = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "TM");
                    se = readBusProperty(SYSTEM_OBJECT, VSYS_IF, "SE");
                }

                replace(mt.begin(), mt.end(), '-', '.');
                expanded.replace(idx, 3, mt + "." + se);
            }
        }
    }
    catch (const exception& e)
    {
        cerr << "Failed to expand location code with exception: " << e.what()
             << "\n";
    }
    return expanded;
}

/**
 * @brief Populate FRU specific interfaces.
 *
 * This is a common method which handles both
 * ipz and keyword specific interfaces thus,
 * reducing the code redundancy.
 * @param[in] map - Reference to the innermost keyword-value map.
 * @param[in] preIntrStr - Reference to the interface string.
 * @param[out] interfaces - Reference to interface map.
 */
template <typename T>
static void populateFruSpecificInterfaces(const T& map,
                                          const string& preIntrStr,
                                          inventory::InterfaceMap& interfaces)
{
    inventory::PropertyMap prop;

    for (const auto& kwVal : map)
    {
        auto kw = kwVal.first;

        if (kw[0] == '#')
        {
            kw = string("PD_") + kw[1];
        }
        else if (isdigit(kw[0]))
        {
            kw = string("N_") + kw;
        }
        if constexpr (is_same<T, KeywordVpdMap>::value)
        {
            if (get_if<Binary>(&kwVal.second))
            {
                Binary vec(get_if<Binary>(&kwVal.second)->begin(),
                           get_if<Binary>(&kwVal.second)->end());
                prop.emplace(move(kw), move(vec));
            }
            else
            {
                if (kw == "MemorySizeInKB")
                {
                    inventory::PropertyMap memProp;
                    auto memVal = get_if<size_t>(&kwVal.second);
                    if (memVal)
                    {
                        memProp.emplace(move(kw),
                                        ((*memVal) * CONVERT_MB_TO_KB));
                        interfaces.emplace(
                            "xyz.openbmc_project.Inventory.Item.Dimm",
                            move(memProp));
                    }
                    else
                    {
                        cerr << "MemorySizeInKB value not found in vpd map\n";
                    }
                }
            }
        }
        else
        {
            Binary vec(kwVal.second.begin(), kwVal.second.end());
            prop.emplace(move(kw), move(vec));
        }
    }

    interfaces.emplace(preIntrStr, move(prop));
}

/**
 * @brief Populate Interfaces.
 *
 * This method populates common and extra interfaces to dbus.
 * @param[in] js - json object
 * @param[out] interfaces - Reference to interface map
 * @param[in] vpdMap - Reference to the parsed vpd map.
 * @param[in] isSystemVpd - Denotes whether we are collecting the system VPD.
 */
template <typename T>
static void populateInterfaces(const nlohmann::json& js,
                               inventory::InterfaceMap& interfaces,
                               const T& vpdMap, bool isSystemVpd)
{
    for (const auto& ifs : js.items())
    {
        string inf = ifs.key();
        inventory::PropertyMap props;

        for (const auto& itr : ifs.value().items())
        {
            const string& busProp = itr.key();

            if (itr.value().is_boolean())
            {
                props.emplace(busProp, itr.value().get<bool>());
            }
            else if (itr.value().is_string())
            {
                if constexpr (is_same<T, Parsed>::value)
                {
                    if (busProp == "LocationCode" &&
                        inf == IBM_LOCATION_CODE_INF)
                    {
                        // TODO deprecate the com.ibm interface later
                        auto prop = expandLocationCode(
                            itr.value().get<string>(), vpdMap, isSystemVpd);
                        props.emplace(busProp, prop);
                        interfaces.emplace(XYZ_LOCATION_CODE_INF, props);
                        interfaces.emplace(IBM_LOCATION_CODE_INF, props);
                    }
                    else
                    {
                        props.emplace(busProp, itr.value().get<string>());
                    }
                }
                else
                {
                    props.emplace(busProp, itr.value().get<string>());
                }
            }
            else if (itr.value().is_array())
            {
                try
                {
                    props.emplace(busProp, itr.value().get<Binary>());
                }
                catch (const nlohmann::detail::type_error& e)
                {
                    std::cerr << "Type exception: " << e.what() << "\n";
                    // Ignore any type errors
                }
            }
            else if (itr.value().is_object())
            {
                const string& rec = itr.value().value("recordName", "");
                const string& kw = itr.value().value("keywordName", "");
                const string& encoding = itr.value().value("encoding", "");

                if constexpr (is_same<T, Parsed>::value)
                {
                    if (!rec.empty() && !kw.empty() && vpdMap.count(rec) &&
                        vpdMap.at(rec).count(kw))
                    {
                        auto encoded =
                            encodeKeyword(vpdMap.at(rec).at(kw), encoding);
                        props.emplace(busProp, encoded);
                    }
                }
                else if constexpr (is_same<T, KeywordVpdMap>::value)
                {
                    if (!kw.empty() && vpdMap.count(kw))
                    {
                        auto kwValue = get_if<Binary>(&vpdMap.at(kw));
                        auto uintValue = get_if<size_t>(&vpdMap.at(kw));

                        if (kwValue)
                        {
                            auto prop =
                                string((*kwValue).begin(), (*kwValue).end());

                            auto encoded = encodeKeyword(prop, encoding);

                            props.emplace(busProp, encoded);
                        }
                        else if (uintValue)
                        {
                            props.emplace(busProp, *uintValue);
                        }
                    }
                }
            }
            else if (itr.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.
                props.emplace(busProp, itr.value().get<size_t>());
            }
        }
        interfaces.emplace(inf, move(props));
    }
}

/*API to reset EEPROM pointer to a safe position to avoid VPD corruption.
 * Currently do reset only for DIMM VPD.*/
static void resetEEPROMPointer(const nlohmann::json& js, const string& file,
                               ifstream& vpdFile)
{
    for (const auto& item : js["frus"][file])
    {
        if (item.find("extraInterfaces") != item.end())
        {
            if (item["extraInterfaces"].find(
                    "xyz.openbmc_project.Inventory.Item.Dimm") !=
                item["extraInterfaces"].end())
            {
                // moves the EEPROM pointer to 2048 'th byte.
                vpdFile.seekg(2047, std::ios::beg);
                // Read that byte and discard - to affirm the move
                // operation.
                char ch;
                vpdFile.read(&ch, sizeof(ch));
            }
            return;
        }
    }
}

static Binary getVpdDataInVector(const nlohmann::json& js, const string& file)
{
    uint32_t offset = 0;
    // check if offset present?
    for (const auto& item : js["frus"][file])
    {
        if (item.find("offset") != item.end())
        {
            offset = item["offset"];
        }
    }

    // TODO: Figure out a better way to get max possible VPD size.
    auto maxVPDSize = std::min(std::filesystem::file_size(file),
                               static_cast<uintmax_t>(65504));

    Binary vpdVector;
    vpdVector.resize(maxVPDSize);
    ifstream vpdFile;
    vpdFile.open(file, ios::binary);

    vpdFile.seekg(offset, ios_base::cur);
    vpdFile.read(reinterpret_cast<char*>(&vpdVector[0]), maxVPDSize);
    vpdVector.resize(vpdFile.gcount());

    resetEEPROMPointer(js, file, vpdFile);

    return vpdVector;
}

/** This API will be called at the end of VPD collection to perform any post
 * actions.
 *
 * @param[in] json - json object
 * @param[in] file - eeprom file path
 */
static void postFailAction(const nlohmann::json& json, const string& file)
{
    if ((json["frus"][file].at(0)).find("postActionFail") ==
        json["frus"][file].at(0).end())
    {
        return;
    }

    uint8_t pinValue = 0;
    string pinName;

    for (const auto& postAction :
         (json["frus"][file].at(0))["postActionFail"].items())
    {
        if (postAction.key() == "pin")
        {
            pinName = postAction.value();
        }
        else if (postAction.key() == "value")
        {
            // Get the value to set
            pinValue = postAction.value();
        }
    }

    cout << "Setting GPIO: " << pinName << " to " << (int)pinValue << endl;

    try
    {
        gpiod::line outputLine = gpiod::find_line(pinName);

        if (!outputLine)
        {
            cout << "Couldn't find output line:" << pinName
                 << " on GPIO. Skipping...\n";

            return;
        }
        outputLine.request(
            {"Disable line", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
            pinValue);
    }
    catch (const system_error&)
    {
        cerr << "Failed to set post-action GPIO" << endl;
    }
}

/** Performs any pre-action needed to get the FRU setup for collection.
 *
 * @param[in] json - json object
 * @param[in] file - eeprom file path
 */
static void preAction(const nlohmann::json& json, const string& file)
{
    if ((json["frus"][file].at(0)).find("preAction") ==
        json["frus"][file].at(0).end())
    {
        return;
    }

    uint8_t pinValue = 0;
    string pinName;

    for (const auto& postAction :
         (json["frus"][file].at(0))["preAction"].items())
    {
        if (postAction.key() == "pin")
        {
            pinName = postAction.value();
        }
        else if (postAction.key() == "value")
        {
            // Get the value to set
            pinValue = postAction.value();
        }
    }

    cout << "Setting GPIO: " << pinName << " to " << (int)pinValue << endl;
    try
    {
        gpiod::line outputLine = gpiod::find_line(pinName);

        if (!outputLine)
        {
            cout << "Couldn't find output line:" << pinName
                 << " on GPIO. Skipping...\n";

            return;
        }
        outputLine.request(
            {"FRU pre-action", ::gpiod::line_request::DIRECTION_OUTPUT, 0},
            pinValue);
    }
    catch (const system_error&)
    {
        cerr << "Failed to set pre-action GPIO" << endl;
        return;
    }

    // Now bind the device
    string bind = json["frus"][file].at(0).value("devAddress", "");
    cout << "Binding device " << bind << endl;
    string bindCmd = string("echo \"") + bind +
                     string("\" > /sys/bus/i2c/drivers/at24/bind");
    cout << bindCmd << endl;
    executeCmd(bindCmd);

    // Check if device showed up (test for file)
    if (!fs::exists(file))
    {
        cout << "EEPROM " << file << " does not exist. Take failure action"
             << endl;
        // If not, then take failure postAction
        postFailAction(json, file);
    }
}

/**
 * @brief Set certain one time properties in the inventory
 * Use this function to insert the Functional and Enabled properties into the
 * inventory map. This function first checks if the object in question already
 * has these properties hosted on D-Bus, if the property is already there, it is
 * not modified, hence the name "one time". If the property is not already
 * present, it will be added to the map with a suitable default value (true for
 * Functional and false for Enabled)
 *
 * @param[in] object - The inventory D-Bus obejct without the inventory prefix.
 * @param[inout] interfaces - Reference to a map of inventory interfaces to
 * which the properties will be attached.
 */
static void setOneTimeProperties(const std::string& object,
                                 inventory::InterfaceMap& interfaces)
{
    auto bus = sdbusplus::bus::new_default();
    auto objectPath = INVENTORY_PATH + object;
    auto prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
                                    objectPath.c_str(),
                                    "org.freedesktop.DBus.Properties", "Get");
    prop.append("xyz.openbmc_project.State.Decorator.OperationalStatus");
    prop.append("Functional");
    try
    {
        auto result = bus.call(prop);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // Treat as property unavailable
        inventory::PropertyMap prop;
        prop.emplace("Functional", true);
        interfaces.emplace(
            "xyz.openbmc_project.State.Decorator.OperationalStatus",
            move(prop));
    }
    prop = bus.new_method_call("xyz.openbmc_project.Inventory.Manager",
                               objectPath.c_str(),
                               "org.freedesktop.DBus.Properties", "Get");
    prop.append("xyz.openbmc_project.Object.Enable");
    prop.append("Enabled");
    try
    {
        auto result = bus.call(prop);
    }
    catch (const sdbusplus::exception::SdBusError& e)
    {
        // Treat as property unavailable
        inventory::PropertyMap prop;
        prop.emplace("Enabled", false);
        interfaces.emplace("xyz.openbmc_project.Object.Enable", move(prop));
    }
}

/**
 * @brief Prime the Inventory
 * Prime the inventory by populating only the location code,
 * type interface and the inventory object for the frus
 * which are not system vpd fru.
 *
 * @param[in] jsObject - Reference to vpd inventory json object
 * @param[in] vpdMap -  Reference to the parsed vpd map
 *
 * @returns Map of items in extraInterface.
 */
template <typename T>
inventory::ObjectMap primeInventory(const nlohmann::json& jsObject,
                                    const T& vpdMap)
{
    inventory::ObjectMap objects;

    for (auto& itemFRUS : jsObject["frus"].items())
    {
        // Take pre actions
        preAction(jsObject, itemFRUS.key());
        for (auto& itemEEPROM : itemFRUS.value())
        {
            inventory::InterfaceMap interfaces;
            inventory::Object object(itemEEPROM.at("inventoryPath"));

            if ((itemFRUS.key() != systemVpdFilePath) &&
                !itemEEPROM.value("noprime", false))
            {
                inventory::PropertyMap presProp;
                presProp.emplace("Present", false);
                interfaces.emplace("xyz.openbmc_project.Inventory.Item",
                                   presProp);
                setOneTimeProperties(object, interfaces);
                if (itemEEPROM.find("extraInterfaces") != itemEEPROM.end())
                {
                    for (const auto& eI : itemEEPROM["extraInterfaces"].items())
                    {
                        inventory::PropertyMap props;
                        if (eI.key() == IBM_LOCATION_CODE_INF)
                        {
                            if constexpr (std::is_same<T, Parsed>::value)
                            {
                                for (auto& lC : eI.value().items())
                                {
                                    auto propVal = expandLocationCode(
                                        lC.value().get<string>(), vpdMap, true);

                                    props.emplace(move(lC.key()),
                                                  move(propVal));
                                    interfaces.emplace(XYZ_LOCATION_CODE_INF,
                                                       props);
                                    interfaces.emplace(move(eI.key()),
                                                       move(props));
                                }
                            }
                        }
                        else if (eI.key().find("Inventory.Item.") !=
                                 string::npos)
                        {
                            interfaces.emplace(move(eI.key()), move(props));
                        }
                        else if (eI.key() ==
                                 "xyz.openbmc_project.Inventory.Item")
                        {
                            for (auto& val : eI.value().items())
                            {
                                if (val.key() == "PrettyName")
                                {
                                    presProp.emplace(val.key(),
                                                     val.value().get<string>());
                                }
                            }
                            // Use insert_or_assign here as we may already have
                            // inserted the present property only earlier in
                            // this function under this same interface.
                            interfaces.insert_or_assign(eI.key(),
                                                        move(presProp));
                        }
                    }
                }
                objects.emplace(move(object), move(interfaces));
            }
        }
    }
    return objects;
}

/**
 * @brief This API executes command to set environment variable
 *        And then reboot the system
 * @param[in] key   -env key to set new value
 * @param[in] value -value to set.
 */
void setEnvAndReboot(const string& key, const string& value)
{
    // set env and reboot and break.
    executeCmd("/sbin/fw_setenv", key, value);
    log<level::INFO>("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);
}

/*
 * @brief This API checks for env var fitconfig.
 *        If not initialised OR updated as per the current system type,
 *        update this env var and reboot the system.
 *
 * @param[in] systemType IM kwd in vpd tells about which system type it is.
 * */
void setDevTreeEnv(const string& systemType)
{
    // Init with default dtb
    string newDeviceTree = "conf-aspeed-bmc-ibm-rainier-p1.dtb";
    static const deviceTreeMap deviceTreeSystemTypeMap = {
        {RAINIER_2U, "conf-aspeed-bmc-ibm-rainier-p1.dtb"},
        {RAINIER_2U_V2, "conf-aspeed-bmc-ibm-rainier.dtb"},
        {RAINIER_4U, "conf-aspeed-bmc-ibm-rainier-4u-p1.dtb"},
        {RAINIER_4U_V2, "conf-aspeed-bmc-ibm-rainier-4u.dtb"},
        {RAINIER_1S4U, "conf-aspeed-bmc-ibm-rainier-1s4u.dtb"},
        {EVEREST, "conf-aspeed-bmc-ibm-everest.dtb"}};

    if (deviceTreeSystemTypeMap.find(systemType) !=
        deviceTreeSystemTypeMap.end())
    {
        newDeviceTree = deviceTreeSystemTypeMap.at(systemType);
    }
    else
    {
        // System type not supported
        string err = "This System type not found/supported in dtb table " +
                     systemType +
                     ".Please check the HW and IM keywords in the system "
                     "VPD.Breaking...";

        // map to hold additional data in case of logging pel
        PelAdditionalData additionalData{};
        additionalData.emplace("DESCRIPTION", err);
        createPEL(additionalData, PelSeverity::WARNING,
                  errIntfForInvalidSystemType);
        exit(-1);
    }

    string readVarValue;
    bool envVarFound = false;

    vector<string> output = executeCmd("/sbin/fw_printenv");
    for (const auto& entry : output)
    {
        size_t pos = entry.find("=");
        string key = entry.substr(0, pos);
        if (key != "fitconfig")
        {
            continue;
        }

        envVarFound = true;
        if (pos + 1 < entry.size())
        {
            readVarValue = entry.substr(pos + 1);
            if (readVarValue.find(newDeviceTree) != string::npos)
            {
                // fitconfig is Updated. No action needed
                break;
            }
        }
        // set env and reboot and break.
        setEnvAndReboot(key, newDeviceTree);
        exit(0);
    }

    // check If env var Not found
    if (!envVarFound)
    {
        setEnvAndReboot("fitconfig", newDeviceTree);
    }
}

/**
 * @brief API to call VPD manager to write VPD to EEPROM.
 * @param[in] Object path.
 * @param[in] record to be updated.
 * @param[in] keyword to be updated.
 * @param[in] keyword data to be updated
 */
void updateHardware(const string& objectName, const string& recName,
                    const string& kwdName, const Binary& data)
{
    try
    {
        auto bus = sdbusplus::bus::new_default();
        auto properties =
            bus.new_method_call(BUSNAME, OBJPATH, IFACE, "WriteKeyword");
        properties.append(
            static_cast<sdbusplus::message::object_path>(objectName));
        properties.append(recName);
        properties.append(kwdName);
        properties.append(data);
        bus.call(properties);
    }
    catch (const sdbusplus::exception::exception& e)
    {
        std::string what =
            "VPDManager WriteKeyword api failed for inventory path " +
            objectName;
        what += " record " + recName;
        what += " keyword " + kwdName;
        what += " with bus error = " + std::string(e.what());

        // map to hold additional data in case of logging pel
        PelAdditionalData additionalData{};
        additionalData.emplace("CALLOUT_INVENTORY_PATH", objectName);
        additionalData.emplace("DESCRIPTION", what);
        createPEL(additionalData, PelSeverity::WARNING, errIntfForBusFailure);
    }
}

/**
 * @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.
 */
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& keyword : kwdListForRecord)
            {
                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);

                    if (busValue.find_first_not_of(' ') != string::npos)
                    {
                        if (kwdValue.find_first_not_of(' ') == string::npos)
                        {
                            // 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));
                        }
                    }
                }
            }
        }
    }
}

/**
 * @brief API to check if we need to restore system VPD
 * This functionality is only applicable for IPZ VPD data.
 * @param[in] vpdMap - IPZ vpd map
 * @param[in] objectPath - Object path for the FRU
 */
void restoreSystemVPD(Parsed& vpdMap, const string& objectPath)
{
    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& keyword : kwdListForRecord)
            {
                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);

                    if (busValue.find_first_not_of(' ') != string::npos)
                    {
                        if (kwdValue.find_first_not_of(' ') != string::npos)
                        {
                            // both the data are present, check for mismatch
                            if (busValue != kwdValue)
                            {
                                string errMsg = "VPD data mismatch on cache "
                                                "and hardware for record: ";
                                errMsg += (*it).first;
                                errMsg += " and keyword: ";
                                errMsg += keyword;

                                // data mismatch
                                PelAdditionalData additionalData;
                                additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                                       objectPath);

                                additionalData.emplace("DESCRIPTION", errMsg);

                                createPEL(additionalData, PelSeverity::WARNING,
                                          errIntfForInvalidVPD);
                            }
                        }
                        else
                        {
                            // implies hardware data is blank
                            // update the map
                            Binary busData(busValue.begin(), busValue.end());

                            // update the map as well, so that cache data is not
                            // updated as blank while populating VPD map on Dbus
                            // in populateDBus Api
                            kwdValue = busValue;
                        }
                    }
                    else if (kwdValue.find_first_not_of(' ') == string::npos)
                    {
                        string errMsg = "VPD is blank on both cache and "
                                        "hardware for record: ";
                        errMsg += (*it).first;
                        errMsg += " and keyword: ";
                        errMsg += keyword;
                        errMsg += ". SSR need to update hardware VPD.";

                        // both the data are blanks, log PEL
                        PelAdditionalData additionalData;
                        additionalData.emplace("CALLOUT_INVENTORY_PATH",
                                               objectPath);

                        additionalData.emplace("DESCRIPTION", errMsg);

                        // log PEL TODO: Block IPL
                        createPEL(additionalData, PelSeverity::ERROR,
                                  errIntfForBlankSystemVPD);
                        continue;
                    }
                }
            }
        }
    }
}

/**
 * @brief This checks for is this FRU a processor
 *        And if yes, then checks for is this primary
 *
 * @param[in] js- vpd json to get the information about this FRU
 * @param[in] filePath- FRU vpd
 *
 * @return true/false
 */
bool isThisPrimaryProcessor(nlohmann::json& js, const string& filePath)
{
    bool isProcessor = false;
    bool isPrimary = false;

    for (const auto& item : js["frus"][filePath])
    {
        if (item.find("extraInterfaces") != item.end())
        {
            for (const auto& eI : item["extraInterfaces"].items())
            {
                if (eI.key().find("Inventory.Item.Cpu") != string::npos)
                {
                    isProcessor = true;
                }
            }
        }

        if (isProcessor)
        {
            string cpuType = item.value("cpuType", "");
            if (cpuType == "primary")
            {
                isPrimary = true;
            }
        }
    }

    return (isProcessor && isPrimary);
}

/**
 * @brief This finds DIMM vpd in vpd json and enables them by binding the device
 *        driver
 * @param[in] js- vpd json to iterate through and take action if it is DIMM
 */
void doEnableAllDimms(nlohmann::json& js)
{
    // iterate over each fru
    for (const auto& eachFru : js["frus"].items())
    {
        // skip the driver binding if eeprom already exists
        if (fs::exists(eachFru.key()))
        {
            continue;
        }

        for (const auto& eachInventory : eachFru.value())
        {
            if (eachInventory.find("extraInterfaces") != eachInventory.end())
            {
                for (const auto& eI : eachInventory["extraInterfaces"].items())
                {
                    if (eI.key().find("Inventory.Item.Dimm") != string::npos)
                    {
                        string dimmVpd = eachFru.key();
                        // fetch it from
                        // "/sys/bus/i2c/drivers/at24/414-0050/eeprom"

                        regex matchPatern("([0-9]+-[0-9]{4})");
                        smatch matchFound;
                        if (regex_search(dimmVpd, matchFound, matchPatern))
                        {
                            vector<string> i2cReg;
                            boost::split(i2cReg, matchFound.str(0),
                                         boost::is_any_of("-"));

                            // remove 0s from begining
                            const regex pattern("^0+(?!$)");
                            for (auto& i : i2cReg)
                            {
                                i = regex_replace(i, pattern, "");
                            }

                            if (i2cReg.size() == 2)
                            {
                                // echo 24c32 0x50 >
                                // /sys/bus/i2c/devices/i2c-16/new_device
                                string cmnd = "echo 24c32 0x" + i2cReg[1] +
                                              " > /sys/bus/i2c/devices/i2c-" +
                                              i2cReg[0] + "/new_device";

                                executeCmd(cmnd);
                            }
                        }
                    }
                }
            }
        }
    }
}

/**
 * @brief Populate Dbus.
 * This method invokes all the populateInterface functions
 * and notifies PIM about dbus object.
 * @param[in] vpdMap - Either IPZ vpd map or Keyword vpd map based on the
 * input.
 * @param[in] js - Inventory json object
 * @param[in] filePath - Path of the vpd file
 * @param[in] preIntrStr - Interface string
 */
template <typename T>
static void populateDbus(T& vpdMap, nlohmann::json& js, const string& filePath)
{
    inventory::InterfaceMap interfaces;
    inventory::ObjectMap objects;
    inventory::PropertyMap prop;
    string ccinFromVpd;

    bool isSystemVpd = (filePath == systemVpdFilePath);
    if constexpr (is_same<T, Parsed>::value)
    {
        ccinFromVpd = getKwVal(vpdMap, "VINI", "CC");
        transform(ccinFromVpd.begin(), ccinFromVpd.end(), ccinFromVpd.begin(),
                  ::toupper);

        if (isSystemVpd)
        {
            std::vector<std::string> interfaces = {motherBoardInterface};
            // call mapper to check for object path creation
            MapperResponse subTree =
                getObjectSubtreeForInterfaces(pimPath, 0, interfaces);
            string mboardPath =
                js["frus"][filePath].at(0).value("inventoryPath", "");

            // Attempt system VPD restore if we have a motherboard
            // object in the inventory.
            if ((subTree.size() != 0) &&
                (subTree.find(pimPath + mboardPath) != subTree.end()))
            {
                restoreSystemVPD(vpdMap, mboardPath);
            }
            else
            {
                log<level::ERR>("No object path found");
            }
        }
        else
        {
            // check if it is processor vpd.
            auto isPrimaryCpu = isThisPrimaryProcessor(js, filePath);

            if (isPrimaryCpu)
            {
                auto ddVersion = getKwVal(vpdMap, "CRP0", "DD");

                auto chipVersion = atoi(ddVersion.substr(1, 2).c_str());

                if (chipVersion >= 2)
                {
                    doEnableAllDimms(js);
                }
            }
        }
    }

    if (isSystemVpd)
    {
        string systemJsonName{};
        if constexpr (is_same<T, Parsed>::value)
        {
            // pick the right system json
            systemJsonName = getSystemsJson(vpdMap);
        }

        fs::path target = systemJsonName;
        fs::path link = INVENTORY_JSON_SYM_LINK;

        // Create the directory for hosting the symlink
        fs::create_directories(VPD_FILES_PATH);
        // unlink the symlink previously created (if any)
        remove(INVENTORY_JSON_SYM_LINK);
        // create a new symlink based on the system
        fs::create_symlink(target, link);

        // Reloading the json
        ifstream inventoryJson(link);
        js = json::parse(inventoryJson);
        inventoryJson.close();
    }

    for (const auto& item : js["frus"][filePath])
    {
        const auto& objectPath = item["inventoryPath"];
        sdbusplus::message::object_path object(objectPath);

        vector<string> ccinList;
        if (item.find("ccin") != item.end())
        {
            for (const auto& cc : item["ccin"])
            {
                string ccin = cc;
                transform(ccin.begin(), ccin.end(), ccin.begin(), ::toupper);
                ccinList.push_back(ccin);
            }
        }

        if (!ccinFromVpd.empty() && !ccinList.empty() &&
            (find(ccinList.begin(), ccinList.end(), ccinFromVpd) ==
             ccinList.end()))
        {
            continue;
        }

        if ((isSystemVpd) || (item.value("noprime", false)))
        {

            // Populate one time properties for the system VPD and its sub-frus
            // and for other non-primeable frus.
            // For the remaining FRUs, this will get handled as a part of
            // priming the inventory.
            setOneTimeProperties(objectPath, interfaces);
        }

        // Populate the VPD keywords and the common interfaces only if we
        // are asked to inherit that data from the VPD, else only add the
        // extraInterfaces.
        if (item.value("inherit", true))
        {
            if constexpr (is_same<T, Parsed>::value)
            {
                // Each record in the VPD becomes an interface and all
                // keyword within the record are properties under that
                // interface.
                for (const auto& record : vpdMap)
                {
                    populateFruSpecificInterfaces(
                        record.second, ipzVpdInf + record.first, interfaces);
                }
            }
            else if constexpr (is_same<T, KeywordVpdMap>::value)
            {
                populateFruSpecificInterfaces(vpdMap, kwdVpdInf, interfaces);
            }
            if (js.find("commonInterfaces") != js.end())
            {
                populateInterfaces(js["commonInterfaces"], interfaces, vpdMap,
                                   isSystemVpd);
            }
        }
        else
        {
            // Check if we have been asked to inherit specific record(s)
            if constexpr (is_same<T, Parsed>::value)
            {
                if (item.find("copyRecords") != item.end())
                {
                    for (const auto& record : item["copyRecords"])
                    {
                        const string& recordName = record;
                        if (vpdMap.find(recordName) != vpdMap.end())
                        {
                            populateFruSpecificInterfaces(
                                vpdMap.at(recordName), ipzVpdInf + recordName,
                                interfaces);
                        }
                    }
                }
            }
        }
        // Populate interfaces and properties that are common to every FRU
        // and additional interface that might be defined on a per-FRU
        // basis.
        if (item.find("extraInterfaces") != item.end())
        {
            populateInterfaces(item["extraInterfaces"], interfaces, vpdMap,
                               isSystemVpd);
        }
        objects.emplace(move(object), move(interfaces));
    }

    if (isSystemVpd)
    {
        inventory::ObjectMap primeObject = primeInventory(js, vpdMap);
        objects.insert(primeObject.begin(), primeObject.end());

        // set the U-boot environment variable for device-tree
        if constexpr (is_same<T, Parsed>::value)
        {
            setDevTreeEnv(fs::path(getSystemsJson(vpdMap)).filename());
        }
    }

    // Notify PIM
    common::utility::callPIM(move(objects));
}

int main(int argc, char** argv)
{
    int rc = 0;
    json js{};
    Binary vpdVector{};
    string file{};
    // map to hold additional data in case of logging pel
    PelAdditionalData additionalData{};

    // this is needed to hold base fru inventory path in case there is ECC or
    // vpd exception while parsing the file
    std::string baseFruInventoryPath = {};

    // severity for PEL
    PelSeverity pelSeverity = PelSeverity::WARNING;

    try
    {
        App app{"ibm-read-vpd - App to read IPZ format VPD, parse it and store "
                "in DBUS"};

        app.add_option("-f, --file", file, "File containing VPD (IPZ/KEYWORD)")
            ->required();

        CLI11_PARSE(app, argc, argv);

        // PEL severity should be ERROR in case of any system VPD failure
        if (file == systemVpdFilePath)
        {
            pelSeverity = PelSeverity::ERROR;
        }

        auto jsonToParse = INVENTORY_JSON_DEFAULT;

        // If the symlink exists, it means it has been setup for us, switch the
        // path
        if (fs::exists(INVENTORY_JSON_SYM_LINK))
        {
            jsonToParse = INVENTORY_JSON_SYM_LINK;
        }

        // Make sure that the file path we get is for a supported EEPROM
        ifstream inventoryJson(jsonToParse);
        if (!inventoryJson)
        {
            throw(VpdJsonException("Failed to access Json path", jsonToParse));
        }

        try
        {
            js = json::parse(inventoryJson);
        }
        catch (const json::parse_error& ex)
        {
            throw(VpdJsonException("Json parsing failed", jsonToParse));
        }

        // Do we have the mandatory "frus" section?
        if (js.find("frus") == js.end())
        {
            throw(VpdJsonException("FRUs section not found in JSON",
                                   jsonToParse));
        }

        // Check if it's a udev path - patterned as(/ahb/ahb:apb/ahb:apb:bus@)
        if (file.find("/ahb:apb") != string::npos)
        {
            // Translate udev path to a generic /sys/bus/.. file path.
            udevToGenericPath(file);

            if ((js["frus"].find(file) != js["frus"].end()) &&
                (file == systemVpdFilePath))
            {
                // We need manager service active to process restoring of
                // system VPD on hardware. So in case any system restore is
                // required, update hardware in the second trigger of parser
                // code for system vpd file path.

                std::vector<std::string> interfaces{motherBoardInterface};

                // call mapper to check for object path creation
                MapperResponse subTree =
                    getObjectSubtreeForInterfaces(pimPath, 0, interfaces);
                string mboardPath =
                    js["frus"][file].at(0).value("inventoryPath", "");

                // Attempt system VPD restore if we have a motherboard
                // object in the inventory.
                if ((subTree.size() != 0) &&
                    (subTree.find(pimPath + mboardPath) != subTree.end()))
                {
                    vpdVector = getVpdDataInVector(js, file);
                    ParserInterface* parser =
                        ParserFactory::getParser(vpdVector);
                    variant<KeywordVpdMap, Store> parseResult;
                    parseResult = parser->parse();

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

                        // if system VPD restore is required, update the
                        // EEPROM
                        for (const auto& item : blankSystemVpdProperties)
                        {
                            updateHardware(get<0>(item), get<1>(item),
                                           get<2>(item), get<3>(item));
                        }
                    }
                    else
                    {
                        std::cout << "Not a valid format to restore system VPD"
                                  << std::endl;
                    }
                    // release the parser object
                    ParserFactory::freeParser(parser);
                }
                else
                {
                    log<level::ERR>("No object path found");
                }
                return 0;
            }
        }

        if (file.empty())
        {
            cerr << "The EEPROM path <" << file << "> is not valid.";
            return 0;
        }
        if (js["frus"].find(file) == js["frus"].end())
        {
            return 0;
        }

        if (!fs::exists(file))
        {
            cout << "Device path: " << file
                 << " does not exist. Spurious udev event? Exiting." << endl;
            return 0;
        }

        baseFruInventoryPath = js["frus"][file][0]["inventoryPath"];
        // Check if we can read the VPD file based on the power state
        // We skip reading VPD when the power is ON in two scenarios:
        // 1) The eeprom we are trying to read is that of the system VPD
        // 2) The JSON tells us that the FRU EEPROM cannot be read when
        // we are powered ON.
        if (js["frus"][file].at(0).value("powerOffOnly", false) ||
            (file == systemVpdFilePath))
        {
            if ("xyz.openbmc_project.State.Chassis.PowerState.On" ==
                getPowerState())
            {
                cout << "This VPD cannot be read when power is ON" << endl;
                return 0;
            }
        }

        try
        {
            vpdVector = getVpdDataInVector(js, file);
            ParserInterface* parser = ParserFactory::getParser(vpdVector);
            variant<KeywordVpdMap, Store> parseResult;
            parseResult = parser->parse();

            if (auto pVal = get_if<Store>(&parseResult))
            {
                populateDbus(pVal->getVpdMap(), js, file);
            }
            else if (auto pVal = get_if<KeywordVpdMap>(&parseResult))
            {
                populateDbus(*pVal, js, file);
            }

            // release the parser object
            ParserFactory::freeParser(parser);
        }
        catch (const exception& e)
        {
            postFailAction(js, file);
            throw;
        }
    }
    catch (const VpdJsonException& ex)
    {
        additionalData.emplace("JSON_PATH", ex.getJsonPath());
        additionalData.emplace("DESCRIPTION", ex.what());
        createPEL(additionalData, pelSeverity, errIntfForJsonFailure);

        cerr << ex.what() << "\n";
        rc = -1;
    }
    catch (const VpdEccException& ex)
    {
        additionalData.emplace("DESCRIPTION", "ECC check failed");
        additionalData.emplace("CALLOUT_INVENTORY_PATH",
                               INVENTORY_PATH + baseFruInventoryPath);
        createPEL(additionalData, pelSeverity, errIntfForEccCheckFail);
        dumpBadVpd(file, vpdVector);
        cerr << ex.what() << "\n";
        rc = -1;
    }
    catch (const VpdDataException& ex)
    {
        additionalData.emplace("DESCRIPTION", "Invalid VPD data");
        additionalData.emplace("CALLOUT_INVENTORY_PATH",
                               INVENTORY_PATH + baseFruInventoryPath);
        createPEL(additionalData, pelSeverity, errIntfForInvalidVPD);
        dumpBadVpd(file, vpdVector);
        cerr << ex.what() << "\n";
        rc = -1;
    }
    catch (const exception& e)
    {
        dumpBadVpd(file, vpdVector);
        cerr << e.what() << "\n";
        rc = -1;
    }

    return rc;
}