#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
        {
            logging::logMessage("Invalid type received for BIOS table.");
            EventLogger::createSyncPel(
                types::ErrorType::FirmwareError, types::SeverityType::Warning,
                __FILE__, __FUNCTION__, 0,
                std::string("Invalid type received for BIOS table."),
                std::nullopt, std::nullopt, std::nullopt, std::nullopt);
            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 uint8_t& i_ammVal)
{
    const std::string l_valtoUpdate =
        (i_ammVal == 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(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
