#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 <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 perfrom 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::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 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)
        {
            // Check if device showed up (test for file)
            if (!filesystem::exists(item))
            {
                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"));
            }
        }
    }
}

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

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

    // 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
    {
        // Set present property of FRU as false as it has been removed.
        // CC data for FRU is also removed as
        // a) FRU is not there so CC does not make sense.
        // b) Sensors dependent on Panel uses CC data.
        inventory::InterfaceMap interfaces{
            {"xyz.openbmc_project.Inventory.Item", {{"Present", false}}},
            {"com.ibm.ipzvpd.VINI", {{"CC", Binary{}}}}};

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

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

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