#include "config.h"

#include "bios_handler.hpp"

#include "constants.hpp"
#include "logger.hpp"

#include <sdbusplus/bus/match.hpp>
#include <utility/common_utility.hpp>
#include <utility/dbus_utility.hpp>

#include <string>

namespace vpd
{
// Template declaration to define APIs.
template class BiosHandler<IbmBiosHandler>;

template <typename T>
void BiosHandler<T>::checkAndListenPldmService()
{
    // Setup a call back match on NameOwnerChanged to determine when PLDM is up.
    static std::shared_ptr<sdbusplus::bus::match_t> l_nameOwnerMatch =
        std::make_shared<sdbusplus::bus::match_t>(
            *m_asioConn,
            sdbusplus::bus::match::rules::nameOwnerChanged(
                constants::pldmServiceName),
            [this](sdbusplus::message_t& l_msg) {
                if (l_msg.is_method_error())
                {
                    logging::logMessage(
                        "Error in reading PLDM name owner changed signal.");
                    return;
                }

                std::string l_name;
                std::string l_newOwner;
                std::string l_oldOwner;

                l_msg.read(l_name, l_oldOwner, l_newOwner);

                if (!l_newOwner.empty() &&
                    (l_name.compare(constants::pldmServiceName) ==
                     constants::STR_CMP_SUCCESS))
                {
                    m_specificBiosHandler->backUpOrRestoreBiosAttributes();

                    // Start listener now that we have done the restore.
                    listenBiosAttributes();

                    //  We don't need the match anymore
                    l_nameOwnerMatch.reset();
                }
            });

    // Based on PLDM service status reset owner match registered above and
    // trigger BIOS attribute sync.
    if (dbusUtility::isServiceRunning(constants::pldmServiceName))
    {
        l_nameOwnerMatch.reset();
        m_specificBiosHandler->backUpOrRestoreBiosAttributes();

        // Start listener now that we have done the restore.
        listenBiosAttributes();
    }
}

template <typename T>
void BiosHandler<T>::listenBiosAttributes()
{
    static std::shared_ptr<sdbusplus::bus::match_t> l_biosMatch =
        std::make_shared<sdbusplus::bus::match_t>(
            *m_asioConn,
            sdbusplus::bus::match::rules::propertiesChanged(
                constants::biosConfigMgrObjPath,
                constants::biosConfigMgrInterface),
            [this](sdbusplus::message_t& l_msg) {
                m_specificBiosHandler->biosAttributesCallback(l_msg);
            });
}

void IbmBiosHandler::biosAttributesCallback(sdbusplus::message_t& i_msg)
{
    if (i_msg.is_method_error())
    {
        logging::logMessage("Error in reading BIOS attribute signal. ");
        return;
    }

    std::string l_objPath;
    types::BiosBaseTableType l_propMap;
    i_msg.read(l_objPath, l_propMap);

    for (auto l_property : l_propMap)
    {
        if (l_property.first != "BaseBIOSTable")
        {
            // Looking for change in Base BIOS table only.
            continue;
        }

        if (auto l_attributeList =
                std::get_if<std::map<std::string, types::BiosProperty>>(
                    &(l_property.second)))
        {
            for (const auto& l_attribute : *l_attributeList)
            {
                if (auto l_val = std::get_if<std::string>(
                        &(std::get<5>(std::get<1>(l_attribute)))))
                {
                    std::string l_attributeName = std::get<0>(l_attribute);
                    if (l_attributeName == "hb_memory_mirror_mode")
                    {
                        saveAmmToVpd(*l_val);
                    }

                    if (l_attributeName == "pvm_keep_and_clear")
                    {
                        saveKeepAndClearToVpd(*l_val);
                    }

                    if (l_attributeName == "pvm_create_default_lpar")
                    {
                        saveCreateDefaultLparToVpd(*l_val);
                    }

                    if (l_attributeName == "pvm_clear_nvram")
                    {
                        saveClearNvramToVpd(*l_val);
                    }

                    continue;
                }

                if (auto l_val = std::get_if<int64_t>(
                        &(std::get<5>(std::get<1>(l_attribute)))))
                {
                    std::string l_attributeName = std::get<0>(l_attribute);
                    if (l_attributeName == "hb_field_core_override")
                    {
                        saveFcoToVpd(*l_val);
                    }
                }
            }
        }
        else
        {
            // TODO: log a predicitive PEL.
            logging::logMessage("Invalid typre received from BIOS table.");
            break;
        }
    }
}

void IbmBiosHandler::backUpOrRestoreBiosAttributes()
{
    // process FCO
    processFieldCoreOverride();

    // process AMM
    processActiveMemoryMirror();

    // process LPAR
    processCreateDefaultLpar();

    // process clear NVRAM
    processClearNvram();

    // process keep and clear
    processKeepAndClear();
}

types::BiosAttributeCurrentValue IbmBiosHandler::readBiosAttribute(
    const std::string& i_attributeName)
{
    types::BiosAttributeCurrentValue l_attrValueVariant =
        dbusUtility::biosGetAttributeMethodCall(i_attributeName);

    return l_attrValueVariant;
}

void IbmBiosHandler::processFieldCoreOverride()
{
    // TODO: Should we avoid doing this at runtime?

    // Read required keyword from Dbus.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::vsysInf, constants::kwdRG);

    if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        // default length of the keyword is 4 bytes.
        if (l_fcoInVpd->size() != constants::VALUE_4)
        {
            logging::logMessage(
                "Invalid value read for FCO from D-Bus. Skipping.");
        }

        //  If FCO in VPD contains anything other that ASCII Space, restore to
        //  BIOS
        if (std::any_of(l_fcoInVpd->cbegin(), l_fcoInVpd->cend(),
                        [](uint8_t l_val) {
                            return l_val != constants::ASCII_OF_SPACE;
                        }))
        {
            // Restore the data to BIOS.
            saveFcoToBios(*l_fcoInVpd);
        }
        else
        {
            types::BiosAttributeCurrentValue l_attrValueVariant =
                readBiosAttribute("hb_field_core_override");

            if (auto l_fcoInBios = std::get_if<int64_t>(&l_attrValueVariant))
            {
                // save the BIOS data to VPD
                saveFcoToVpd(*l_fcoInBios);

                return;
            }
            logging::logMessage("Invalid type recieved for FCO from BIOS.");
        }
        return;
    }
    logging::logMessage("Invalid type recieved for FCO from VPD.");
}

void IbmBiosHandler::saveFcoToVpd(int64_t i_fcoInBios)
{
    if (i_fcoInBios < 0)
    {
        logging::logMessage("Invalid FCO value in BIOS. Skip updating to VPD");
        return;
    }

    // Read required keyword from Dbus.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::vsysInf, constants::kwdRG);

    if (auto l_fcoInVpd = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        // default length of the keyword is 4 bytes.
        if (l_fcoInVpd->size() != constants::VALUE_4)
        {
            logging::logMessage(
                "Invalid value read for FCO from D-Bus. Skipping.");
            return;
        }

        // convert to VPD value type
        types::BinaryVector l_biosValInVpdFormat = {
            0, 0, 0, static_cast<uint8_t>(i_fcoInBios)};

        // Update only when the data are different.
        if (std::memcmp(l_biosValInVpdFormat.data(), l_fcoInVpd->data(),
                        constants::VALUE_4) != constants::SUCCESS)
        {
            if (constants::FAILURE ==
                m_manager->updateKeyword(
                    SYSTEM_VPD_FILE_PATH,
                    types::IpzData("VSYS", constants::kwdRG,
                                   l_biosValInVpdFormat)))
            {
                logging::logMessage(
                    "Failed to update " + std::string(constants::kwdRG) +
                    " keyword to VPD.");
            }
        }
    }
    else
    {
        logging::logMessage("Invalid type read for FCO from DBus.");
    }
}

void IbmBiosHandler::saveFcoToBios(const types::BinaryVector& i_fcoVal)
{
    if (i_fcoVal.size() != constants::VALUE_4)
    {
        logging::logMessage("Bad size for FCO received. Skip writing to BIOS");
        return;
    }

    types::PendingBIOSAttrs l_pendingBiosAttribute;
    l_pendingBiosAttribute.push_back(std::make_pair(
        "hb_field_core_override",
        std::make_tuple(
            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Integer",
            i_fcoVal.at(constants::VALUE_3))));

    if (!dbusUtility::writeDbusProperty(
            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
            constants::biosConfigMgrInterface, "PendingAttributes",
            l_pendingBiosAttribute))
    {
        // TODO: Should we log informational PEL here as well?
        logging::logMessage(
            "DBus call to update FCO value in pending attribute failed. ");
    }
}

void IbmBiosHandler::saveAmmToVpd(const std::string& i_memoryMirrorMode)
{
    if (i_memoryMirrorMode.empty())
    {
        logging::logMessage(
            "Empty memory mirror mode value from BIOS. Skip writing to VPD");
        return;
    }

    // Read existing value.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdAMM);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        auto l_ammValInVpd = *l_pVal;

        types::BinaryVector l_valToUpdateInVpd{
            (i_memoryMirrorMode == "Enabled" ? constants::AMM_ENABLED_IN_VPD
                                             : constants::AMM_DISABLED_IN_VPD)};

        // Check if value is already updated on VPD.
        if (l_ammValInVpd.at(0) == l_valToUpdateInVpd.at(0))
        {
            return;
        }

        if (constants::FAILURE ==
            m_manager->updateKeyword(
                SYSTEM_VPD_FILE_PATH,
                types::IpzData("UTIL", constants::kwdAMM, l_valToUpdateInVpd)))
        {
            logging::logMessage(
                "Failed to update " + std::string(constants::kwdAMM) +
                " keyword to VPD");
        }
    }
    else
    {
        // TODO: Add PEL
        logging::logMessage(
            "Invalid type read for memory mirror mode value from DBus. Skip writing to VPD");
    }
}

void IbmBiosHandler::saveAmmToBios(const std::string& i_ammVal)
{
    if (i_ammVal.size() != constants::VALUE_1)
    {
        logging::logMessage("Bad size for AMM received, Skip writing to BIOS");
        return;
    }

    const std::string l_valtoUpdate =
        (i_ammVal.at(0) == constants::VALUE_2) ? "Enabled" : "Disabled";

    types::PendingBIOSAttrs l_pendingBiosAttribute;
    l_pendingBiosAttribute.push_back(std::make_pair(
        "hb_memory_mirror_mode",
        std::make_tuple(
            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
            l_valtoUpdate)));

    if (!dbusUtility::writeDbusProperty(
            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
            constants::biosConfigMgrInterface, "PendingAttributes",
            l_pendingBiosAttribute))
    {
        // TODO: Should we log informational PEL here as well?
        logging::logMessage(
            "DBus call to update AMM value in pending attribute failed.");
    }
}

void IbmBiosHandler::processActiveMemoryMirror()
{
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdAMM);

    if (auto pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        auto l_ammValInVpd = *pVal;

        // Check if active memory mirror value is default in VPD.
        if (l_ammValInVpd.at(0) == constants::VALUE_0)
        {
            types::BiosAttributeCurrentValue l_attrValueVariant =
                readBiosAttribute("hb_memory_mirror_mode");

            if (auto pVal = std::get_if<std::string>(&l_attrValueVariant))
            {
                saveAmmToVpd(*pVal);
                return;
            }
            logging::logMessage(
                "Invalid type recieved for auto memory mirror mode from BIOS.");
            return;
        }
        else
        {
            saveAmmToBios(std::to_string(l_ammValInVpd.at(0)));
        }
        return;
    }
    logging::logMessage(
        "Invalid type recieved for auto memory mirror mode from VPD.");
}

void IbmBiosHandler::saveCreateDefaultLparToVpd(
    const std::string& i_createDefaultLparVal)
{
    if (i_createDefaultLparVal.empty())
    {
        logging::logMessage(
            "Empty value received for Lpar from BIOS. Skip writing in VPD.");
        return;
    }

    // Read required keyword from DBus as we need to set only a Bit.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        commonUtility::toLower(
            const_cast<std::string&>(i_createDefaultLparVal));

        // Check for second bit. Bit set for enabled else disabled.
        if (((((*l_pVal).at(0) & 0x02) == 0x02) &&
             (i_createDefaultLparVal.compare("enabled") ==
              constants::STR_CMP_SUCCESS)) ||
            ((((*l_pVal).at(0) & 0x02) == 0x00) &&
             (i_createDefaultLparVal.compare("disabled") ==
              constants::STR_CMP_SUCCESS)))
        {
            // Values are same, Don;t update.
            return;
        }

        types::BinaryVector l_valToUpdateInVpd;
        if (i_createDefaultLparVal.compare("enabled") ==
            constants::STR_CMP_SUCCESS)
        {
            // 2nd Bit is used to store the value.
            l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) | 0x02);
        }
        else
        {
            // 2nd Bit is used to store the value.
            l_valToUpdateInVpd.emplace_back((*l_pVal).at(0) & ~(0x02));
        }

        if (-1 ==
            m_manager->updateKeyword(
                SYSTEM_VPD_FILE_PATH,
                types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
                               l_valToUpdateInVpd)))
        {
            logging::logMessage(
                "Failed to update " +
                std::string(constants::kwdClearNVRAM_CreateLPAR) +
                " keyword to VPD");
        }

        return;
    }
    logging::logMessage(
        "Invalid type recieved for create default Lpar from VPD.");
}

void IbmBiosHandler::saveCreateDefaultLparToBios(
    const std::string& i_createDefaultLparVal)
{
    // checking for exact length as it is a string and can have garbage value.
    if (i_createDefaultLparVal.size() != constants::VALUE_1)
    {
        logging::logMessage(
            "Bad size for Create default LPAR in VPD. Skip writing to BIOS.");
        return;
    }

    std::string l_valtoUpdate =
        (i_createDefaultLparVal.at(0) & 0x02) ? "Enabled" : "Disabled";

    types::PendingBIOSAttrs l_pendingBiosAttribute;
    l_pendingBiosAttribute.push_back(std::make_pair(
        "pvm_create_default_lpar",
        std::make_tuple(
            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
            l_valtoUpdate)));

    if (!dbusUtility::writeDbusProperty(
            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
            constants::biosConfigMgrInterface, "PendingAttributes",
            l_pendingBiosAttribute))
    {
        logging::logMessage(
            "DBus call to update lpar value in pending attribute failed.");
    }

    return;
}

void IbmBiosHandler::processCreateDefaultLpar()
{
    // Read required keyword from DBus.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        saveCreateDefaultLparToBios(std::to_string(l_pVal->at(0)));
        return;
    }
    logging::logMessage(
        "Invalid type recieved for create default Lpar from VPD.");
}

void IbmBiosHandler::saveClearNvramToVpd(const std::string& i_clearNvramVal)
{
    if (i_clearNvramVal.empty())
    {
        logging::logMessage(
            "Empty value received for clear NVRAM from BIOS. Skip updating to VPD.");
        return;
    }

    // Read required keyword from DBus as we need to set only a Bit.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        commonUtility::toLower(const_cast<std::string&>(i_clearNvramVal));

        // Check for third bit. Bit set for enabled else disabled.
        if (((((*l_pVal).at(0) & 0x04) == 0x04) &&
             (i_clearNvramVal.compare("enabled") ==
              constants::STR_CMP_SUCCESS)) ||
            ((((*l_pVal).at(0) & 0x04) == 0x00) &&
             (i_clearNvramVal.compare("disabled") ==
              constants::STR_CMP_SUCCESS)))
        {
            // Don't update, values are same.
            return;
        }

        types::BinaryVector l_valToUpdateInVpd;
        if (i_clearNvramVal.compare("enabled") == constants::STR_CMP_SUCCESS)
        {
            // 3rd bit is used to store the value.
            l_valToUpdateInVpd.emplace_back(
                (*l_pVal).at(0) | constants::VALUE_4);
        }
        else
        {
            // 3rd bit is used to store the value.
            l_valToUpdateInVpd.emplace_back(
                (*l_pVal).at(0) & ~(constants::VALUE_4));
        }

        if (-1 ==
            m_manager->updateKeyword(
                SYSTEM_VPD_FILE_PATH,
                types::IpzData("UTIL", constants::kwdClearNVRAM_CreateLPAR,
                               l_valToUpdateInVpd)))
        {
            logging::logMessage(
                "Failed to update " +
                std::string(constants::kwdClearNVRAM_CreateLPAR) +
                " keyword to VPD");
        }

        return;
    }
    logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
}

void IbmBiosHandler::saveClearNvramToBios(const std::string& i_clearNvramVal)
{
    // Check for the exact length as it is a string and it can have a garbage
    // value.
    if (i_clearNvramVal.size() != constants::VALUE_1)
    {
        logging::logMessage(
            "Bad size for clear NVRAM in VPD. Skip writing to BIOS.");
        return;
    }

    // 3rd bit is used to store clear NVRAM value.
    std::string l_valtoUpdate =
        (i_clearNvramVal.at(0) & constants::VALUE_4) ? "Enabled" : "Disabled";

    types::PendingBIOSAttrs l_pendingBiosAttribute;
    l_pendingBiosAttribute.push_back(std::make_pair(
        "pvm_clear_nvram",
        std::make_tuple(
            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
            l_valtoUpdate)));

    if (!dbusUtility::writeDbusProperty(
            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
            constants::biosConfigMgrInterface, "PendingAttributes",
            l_pendingBiosAttribute))
    {
        logging::logMessage(
            "DBus call to update NVRAM value in pending attribute failed.");
    }
}

void IbmBiosHandler::processClearNvram()
{
    // Read required keyword from VPD.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdClearNVRAM_CreateLPAR);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        saveClearNvramToBios(std::to_string(l_pVal->at(0)));
        return;
    }
    logging::logMessage("Invalid type recieved for clear NVRAM from VPD.");
}

void IbmBiosHandler::saveKeepAndClearToVpd(const std::string& i_KeepAndClearVal)
{
    if (i_KeepAndClearVal.empty())
    {
        logging::logMessage(
            "Empty value received for keep and clear from BIOS. Skip updating to VPD.");
        return;
    }

    // Read required keyword from DBus as we need to set only a Bit.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdKeepAndClear);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        commonUtility::toLower(const_cast<std::string&>(i_KeepAndClearVal));

        // Check for first bit. Bit set for enabled else disabled.
        if (((((*l_pVal).at(0) & 0x01) == 0x01) &&
             (i_KeepAndClearVal.compare("enabled") ==
              constants::STR_CMP_SUCCESS)) ||
            ((((*l_pVal).at(0) & 0x01) == 0x00) &&
             (i_KeepAndClearVal.compare("disabled") ==
              constants::STR_CMP_SUCCESS)))
        {
            // Don't update, values are same.
            return;
        }

        types::BinaryVector l_valToUpdateInVpd;
        if (i_KeepAndClearVal.compare("enabled") == constants::STR_CMP_SUCCESS)
        {
            // 1st bit is used to store the value.
            l_valToUpdateInVpd.emplace_back(
                (*l_pVal).at(0) | constants::VALUE_1);
        }
        else
        {
            // 1st bit is used to store the value.
            l_valToUpdateInVpd.emplace_back(
                (*l_pVal).at(0) & ~(constants::VALUE_1));
        }

        if (-1 == m_manager->updateKeyword(
                      SYSTEM_VPD_FILE_PATH,
                      types::IpzData("UTIL", constants::kwdKeepAndClear,
                                     l_valToUpdateInVpd)))
        {
            logging::logMessage(
                "Failed to update " + std::string(constants::kwdKeepAndClear) +
                " keyword to VPD");
        }

        return;
    }
    logging::logMessage("Invalid type recieved for keep and clear from VPD.");
}

void IbmBiosHandler::saveKeepAndClearToBios(
    const std::string& i_KeepAndClearVal)
{
    // checking for exact length as it is a string and can have garbage value.
    if (i_KeepAndClearVal.size() != constants::VALUE_1)
    {
        logging::logMessage(
            "Bad size for keep and clear in VPD. Skip writing to BIOS.");
        return;
    }

    // 1st bit is used to store keep and clear value.
    std::string l_valtoUpdate =
        (i_KeepAndClearVal.at(0) & constants::VALUE_1) ? "Enabled" : "Disabled";

    types::PendingBIOSAttrs l_pendingBiosAttribute;
    l_pendingBiosAttribute.push_back(std::make_pair(
        "pvm_keep_and_clear",
        std::make_tuple(
            "xyz.openbmc_project.BIOSConfig.Manager.AttributeType.Enumeration",
            l_valtoUpdate)));

    if (!dbusUtility::writeDbusProperty(
            constants::biosConfigMgrService, constants::biosConfigMgrObjPath,
            constants::biosConfigMgrInterface, "PendingAttributes",
            l_pendingBiosAttribute))
    {
        logging::logMessage(
            "DBus call to update keep and clear value in pending attribute failed.");
    }
}

void IbmBiosHandler::processKeepAndClear()
{
    // Read required keyword from VPD.
    auto l_kwdValueVariant = dbusUtility::readDbusProperty(
        constants::pimServiceName, constants::systemVpdInvPath,
        constants::utilInf, constants::kwdKeepAndClear);

    if (auto l_pVal = std::get_if<types::BinaryVector>(&l_kwdValueVariant))
    {
        saveKeepAndClearToBios(std::to_string(l_pVal->at(0)));
        return;
    }
    logging::logMessage("Invalid type recieved for keep and clear from VPD.");
}
} // namespace vpd
