#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
