#include "config.h"

#include "item_updater.hpp"

#include "images.hpp"
#include "serialize.hpp"
#include "version.hpp"
#include "xyz/openbmc_project/Software/ExtendedVersion/server.hpp"
#include "xyz/openbmc_project/Software/Version/server.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/elog.hpp>
#include <phosphor-logging/lg2.hpp>
#include <xyz/openbmc_project/Common/error.hpp>
#include <xyz/openbmc_project/Software/Image/error.hpp>

#include <filesystem>
#include <fstream>
#include <queue>
#include <set>
#include <string>
#include <system_error>

namespace phosphor
{
namespace software
{
namespace updater
{

// When you see server:: you know we're referencing our base class
namespace server = sdbusplus::server::xyz::openbmc_project::software;
namespace control = sdbusplus::server::xyz::openbmc_project::control;

PHOSPHOR_LOG2_USING;
using namespace phosphor::logging;
using namespace sdbusplus::error::xyz::openbmc_project::software::image;
using namespace phosphor::software::image;
namespace fs = std::filesystem;
using NotAllowed = sdbusplus::error::xyz::openbmc_project::common::NotAllowed;

void ItemUpdater::createActivation(sdbusplus::message_t& msg)
{
    using SVersion = server::Version;
    using VersionPurpose = SVersion::VersionPurpose;

    sdbusplus::message::object_path objPath;
    auto purpose = VersionPurpose::Unknown;
    std::string extendedVersion;
    std::string version;
    std::map<std::string,
             std::map<std::string,
                      std::variant<std::string, std::vector<std::string>>>>
        interfaces;
    msg.read(objPath, interfaces);
    std::string path(std::move(objPath));
    std::string filePath;
    std::vector<std::string> compatibleNames;

    for (const auto& intf : interfaces)
    {
        if (intf.first == VERSION_IFACE)
        {
            for (const auto& property : intf.second)
            {
                if (property.first == "Purpose")
                {
                    auto value = SVersion::convertVersionPurposeFromString(
                        std::get<std::string>(property.second));
                    if (value == VersionPurpose::BMC ||
#ifdef HOST_BIOS_UPGRADE
                        value == VersionPurpose::Host ||
#endif
                        value == VersionPurpose::System)
                    {
                        purpose = value;
                    }
                }
                else if (property.first == "Version")
                {
                    version = std::get<std::string>(property.second);
                }
            }
        }
        else if (intf.first == FILEPATH_IFACE)
        {
            for (const auto& property : intf.second)
            {
                if (property.first == "Path")
                {
                    filePath = std::get<std::string>(property.second);
                }
            }
        }
        else if (intf.first == EXTENDED_VERSION_IFACE)
        {
            for (const auto& property : intf.second)
            {
                if (property.first == "ExtendedVersion")
                {
                    extendedVersion = std::get<std::string>(property.second);
                }
            }
        }
        else if (intf.first == COMPATIBLE_IFACE)
        {
            for (const auto& property : intf.second)
            {
                if (property.first == "Names")
                {
                    compatibleNames =
                        std::get<std::vector<std::string>>(property.second);
                }
            }
        }
    }
    if (version.empty() || filePath.empty() ||
        purpose == VersionPurpose::Unknown)
    {
        return;
    }

    // Version id is the last item in the path
    auto pos = path.rfind('/');
    if (pos == std::string::npos)
    {
        error("No version id found in object path: {PATH}", "PATH", path);
        return;
    }

    auto versionId = path.substr(pos + 1);

    if (activations.find(versionId) == activations.end())
    {
        verifyAndCreateObjects(versionId, path, version, purpose,
                               extendedVersion, filePath, compatibleNames);
    }
    return;
}

void ItemUpdater::createActivationWithApplyTime(
    std::string& id, std::string& path,
    ApplyTimeIntf::RequestedApplyTimes applyTime)
{
    info("Creating Activation object for id: {ID}", "ID", id);
    AssociationList associations = {};
    // Create an association to the BMC inventory item
    associations.emplace_back(
        std::make_tuple(ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
                        bmcInventoryPath));
    activations.insert(std::make_pair(
        id, std::make_unique<Activation>(
                bus, path, *this, id, server::Activation::Activations::NotReady,
                associations)));
    activations[id]->applyTime = applyTime;
}

ActivationIntf::Activations ItemUpdater::verifyAndCreateObjects(
    std::string& id, std::string& path, std::string& version,
    VersionClass::VersionPurpose purpose, std::string& extendedVersion,
    std ::string& filePath, std::vector<std::string>& compatibleNames)
{
    // Determine the Activation state by processing the given image dir.
    auto activationState = server::Activation::Activations::Invalid;
    ItemUpdater::ActivationStatus result;
    if (purpose == VersionPurpose::BMC || purpose == VersionPurpose::System)
    {
        result = ItemUpdater::validateSquashFSImage(filePath);
    }
    else
    {
        result = ItemUpdater::ActivationStatus::ready;
    }

    AssociationList associations = {};

    if (result == ItemUpdater::ActivationStatus::ready)
    {
        activationState = server::Activation::Activations::Ready;
        // Create an association to the BMC inventory item
        associations.emplace_back(
            std::make_tuple(ACTIVATION_FWD_ASSOCIATION,
                            ACTIVATION_REV_ASSOCIATION, bmcInventoryPath));
    }

    auto versionPtr = std::make_unique<VersionClass>(
        bus, path, version, purpose, extendedVersion, filePath, compatibleNames,
        std::bind(&ItemUpdater::erase, this, std::placeholders::_1), id);
    versionPtr->deleteObject =
        std::make_unique<phosphor::software::manager::Delete>(
            bus, path, *versionPtr);
    versions.insert(std::make_pair(id, std::move(versionPtr)));

    auto activation = activations.find(id);
    if (activation == activations.end())
    {
        activations.insert(std::make_pair(
            id, std::make_unique<Activation>(bus, path, *this, id,
                                             activationState, associations)));
    }
    else
    {
        activation->second->activation(activationState);
    }
    return activationState;
}

bool ItemUpdater::requestActivation(std::string& id)
{
    auto activation = activations.find(id);
    if (activation == activations.end())
    {
        error("Activation object not found for id: {ID}", "ID", id);
        return false;
    }
    activation->second->requestedActivation(
        server::Activation::RequestedActivations::Active);
    return true;
}

bool ItemUpdater::updateActivationStatus(std::string& id,
                                         ActivationIntf::Activations status)
{
    auto activation = activations.find(id);
    if (activation == activations.end())
    {
        error("Activation object not found for id: {ID}", "ID", id);
        return false;
    }
    activation->second->activation(status);
    return true;
}

void ItemUpdater::createUpdateObject(const std::string& id,
                                     const std::string& path)
{
    if (updateManagers.find(id) != updateManagers.end())
    {
        error("UpdateManager object already exists for id: {ID}", "ID", id);
        return;
    }
    updateManagers.insert(
        std::make_pair(id, std::make_unique<UpdateManager>(ctx, path, *this)));
}

void ItemUpdater::processBMCImage()
{
    using VersionClass = phosphor::software::manager::Version;

    // Check MEDIA_DIR and create if it does not exist
    try
    {
        if (!fs::is_directory(MEDIA_DIR))
        {
            fs::create_directory(MEDIA_DIR);
        }
    }
    catch (const fs::filesystem_error& e)
    {
        error("Failed to prepare dir: {ERROR}", "ERROR", e);
        return;
    }

    // Functional images are mounted as rofs-<location>-functional
    constexpr auto functionalSuffix = "-functional";
    bool functionalFound = false;

    // Read os-release from folders under /media/ to get
    // BMC Software Versions.
    std::error_code ec;
    for (const auto& iter : fs::directory_iterator(MEDIA_DIR, ec))
    {
        auto activationState = server::Activation::Activations::Active;
        static const auto BMC_RO_PREFIX_LEN = strlen(BMC_ROFS_PREFIX);

        // Check if the BMC_RO_PREFIXis the prefix of the iter.path
        if (0 ==
            iter.path().native().compare(0, BMC_RO_PREFIX_LEN, BMC_ROFS_PREFIX))
        {
            // Get the version to calculate the id
            fs::path releaseFile(OS_RELEASE_FILE);
            auto osRelease = iter.path() / releaseFile.relative_path();
            if (!fs::is_regular_file(osRelease, ec))
            {
#ifdef BMC_STATIC_DUAL_IMAGE
                // For dual image, it is possible that the secondary image is
                // empty or contains invalid data, ignore such case.
                info("Unable to find osRelease: {PATH}: {ERROR_MSG}", "PATH",
                     osRelease, "ERROR_MSG", ec.message());
#else
                error("Failed to read osRelease: {PATH}: {ERROR_MSG}", "PATH",
                      osRelease, "ERROR_MSG", ec.message());

                // Try to get the version id from the mount directory name and
                // call to delete it as this version may be corrupted. Dynamic
                // volumes created by the UBI layout for example have the id in
                // the mount directory name. The worst that can happen is that
                // erase() is called with an non-existent id and returns.
                auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
                ItemUpdater::erase(id);
#endif

                continue;
            }
            auto version = VersionClass::getBMCVersion(osRelease);
            if (version.empty())
            {
                error("Failed to read version from osRelease: {PATH}", "PATH",
                      osRelease);

                // Try to delete the version, same as above if the
                // OS_RELEASE_FILE does not exist.
                auto id = iter.path().native().substr(BMC_RO_PREFIX_LEN);
                ItemUpdater::erase(id);

                continue;
            }

            // The flash location is part of the mount name: rofs-<location>
            auto flashId = iter.path().native().substr(BMC_RO_PREFIX_LEN);

            auto id = VersionClass::getId(version + flashId);

            // Check if the id has already been added. This can happen if the
            // BMC partitions / devices were manually flashed with the same
            // image.
            if (versions.find(id) != versions.end())
            {
                continue;
            }

            auto functional = false;
            if (iter.path().native().find(functionalSuffix) !=
                std::string::npos)
            {
                // Set functional to true and remove the functional suffix
                functional = true;
                flashId.erase(flashId.length() - strlen(functionalSuffix));
                functionalFound = true;
            }

            auto purpose = server::Version::VersionPurpose::BMC;
            restorePurpose(flashId, purpose);

            // Read os-release from /etc/ to get the BMC extended version
            std::string extendedVersion =
                VersionClass::getBMCExtendedVersion(osRelease);

            auto path = fs::path(SOFTWARE_OBJPATH) / id;

            // Create functional association and minimum ship level instance if
            // this is the functional version
            if (functional)
            {
                createFunctionalAssociation(path);

                if (minimum_ship_level::enabled())
                {
                    minimumVersionObject =
                        std::make_unique<MinimumVersion>(bus, path);
                    minimumVersionObject->minimumVersion(
                        minimum_ship_level::getMinimumVersion());
                }
            }

            AssociationList associations;

            if (activationState == server::Activation::Activations::Active)
            {
                // Create an association to the BMC inventory item
                associations.emplace_back(std::make_tuple(
                    ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
                    bmcInventoryPath));

                // Create an active association since this image is active
                createActiveAssociation(path);
            }

            // Create Version instance for this version.
            auto versionPtr = std::make_unique<VersionClass>(
                bus, path, version, purpose, extendedVersion, flashId,
                std::vector<std::string>(),
                std::bind(&ItemUpdater::erase, this, std::placeholders::_1),
                id);
            if (functional)
            {
                versionPtr->setFunctional(true);
            }
            else
            {
                versionPtr->deleteObject =
                    std::make_unique<phosphor::software::manager::Delete>(
                        bus, path, *versionPtr);
            }
            versions.insert(std::make_pair(id, std::move(versionPtr)));

            // Create Activation instance for this version.
            activations.insert(std::make_pair(
                id, std::make_unique<Activation>(
                        bus, path, *this, id, activationState, associations)));

#ifdef BMC_STATIC_DUAL_IMAGE
            uint8_t priority;
            if ((functional && (runningImageSlot == 0)) ||
                (!functional && (runningImageSlot == 1)))
            {
                priority = 0;
            }
            else
            {
                priority = 1;
            }
            activations.find(id)->second->redundancyPriority =
                std::make_unique<RedundancyPriority>(
                    bus, path, *(activations.find(id)->second), priority,
                    false);
#else
            // If Active, create RedundancyPriority instance for this
            // version.
            if (activationState == server::Activation::Activations::Active)
            {
                uint8_t priority = std::numeric_limits<uint8_t>::max();
                if (!restorePriority(flashId, priority))
                {
                    if (functional)
                    {
                        priority = 0;
                    }
                    else
                    {
                        error(
                            "Unable to restore priority from file for {VERSIONID}",
                            "VERSIONID", id);
                    }
                }
                activations.find(id)->second->redundancyPriority =
                    std::make_unique<RedundancyPriority>(
                        bus, path, *(activations.find(id)->second), priority,
                        false);
            }
#endif
        }
    }

    for (const auto& version : versions)
    {
        if ((versions.size() == 1) || (!version.second->isFunctional()))
        {
            // This is the only BMC version or the non-functional BMC version
            // (in a system with more than one flash), hence create Update
            // object and Updateable association for this version
            if (useUpdateDBusInterface)
            {
                createUpdateObject(version.first, version.second->objPath);
            }
            createUpdateableAssociation(version.second->objPath);
        }
    }

    if (!functionalFound)
    {
        // If there is no functional version found, read the /etc/os-release and
        // create rofs-<versionId>-functional under MEDIA_DIR, then call again
        // processBMCImage() to create the D-Bus interface for it.
        auto version = VersionClass::getBMCVersion(OS_RELEASE_FILE);
        auto id = phosphor::software::manager::Version::getId(
            version + functionalSuffix);
        auto versionFileDir = BMC_ROFS_PREFIX + id + functionalSuffix + "/etc/";
        try
        {
            if (!fs::is_directory(versionFileDir))
            {
                fs::create_directories(versionFileDir);
            }
            auto versionFilePath =
                BMC_ROFS_PREFIX + id + functionalSuffix + OS_RELEASE_FILE;
            fs::create_directory_symlink(OS_RELEASE_FILE, versionFilePath);
            ItemUpdater::processBMCImage();
        }
        catch (const std::exception& e)
        {
            error("Exception during processing: {ERROR}", "ERROR", e);
        }
    }

    mirrorUbootToAlt();
    return;
}

void ItemUpdater::erase(std::string entryId)
{
    // Find entry in versions map
    auto it = versions.find(entryId);
    if (it != versions.end())
    {
        if (it->second->isFunctional() && ACTIVE_BMC_MAX_ALLOWED > 1)
        {
            error(
                "Version ({VERSIONID}) is currently running on the BMC; unable to remove.",
                "VERSIONID", entryId);
            return;
        }
    }

    // First call resetUbootEnvVars() so that the BMC points to a valid image to
    // boot from. If resetUbootEnvVars() is called after the image is actually
    // deleted from the BMC flash, there'd be a time window where the BMC would
    // be pointing to a non-existent image to boot from.
    // Need to remove the entries from the activations map before that call so
    // that resetUbootEnvVars() doesn't use the version to be deleted.
    auto iteratorActivations = activations.find(entryId);
    if (iteratorActivations == activations.end())
    {
        error(
            "Failed to find version ({VERSIONID}) in item updater activations map; unable to remove.",
            "VERSIONID", entryId);
    }
    else
    {
        removeAssociations(iteratorActivations->second->path);
        iteratorActivations->second->deleteImageManagerObject();
        this->activations.erase(entryId);
    }
    ItemUpdater::resetUbootEnvVars();

    if (it != versions.end())
    {
        auto flashId = it->second->path();

        // Delete version data if it has been installed on flash (path is not
        // the upload directory)
        if (flashId.find(IMG_UPLOAD_DIR) == std::string::npos)
        {
            removeReadOnlyPartition(entryId);
            removePersistDataDirectory(flashId);
            helper.clearEntry(flashId);
        }

        // Removing entry in versions map
        this->versions.erase(entryId);
    }

    // Removing entry in updateManagers map
    auto updateManagerIt = updateManagers.find(entryId);
    if (updateManagerIt != updateManagers.end())
    {
        updateManagers.erase(entryId);
    }

    return;
}

void ItemUpdater::deleteAll()
{
    std::vector<std::string> deletableVersions;

    for (const auto& versionIt : versions)
    {
        if (!versionIt.second->isFunctional())
        {
            deletableVersions.push_back(versionIt.first);
        }
    }

    for (const auto& deletableIt : deletableVersions)
    {
        ItemUpdater::erase(deletableIt);
    }

    helper.cleanup();
}

ItemUpdater::ActivationStatus
    ItemUpdater::validateSquashFSImage(const std::string& filePath)
{
    bool valid = true;

    // Record the images which are being updated
    // First check for the fullimage, then check for images with partitions
    imageUpdateList.push_back(bmcFullImages);
    valid = checkImage(filePath, imageUpdateList);
    if (!valid)
    {
        imageUpdateList.clear();
        imageUpdateList.assign(bmcImages.begin(), bmcImages.end());
        valid = checkImage(filePath, imageUpdateList);
        if (!valid)
        {
            error("Failed to find the needed BMC images.");
            return ItemUpdater::ActivationStatus::invalid;
        }
    }

    return ItemUpdater::ActivationStatus::ready;
}

void ItemUpdater::savePriority(const std::string& versionId, uint8_t value)
{
    auto flashId = versions.find(versionId)->second->path();
    storePriority(flashId, value);
    helper.setEntry(flashId, value);
}

void ItemUpdater::freePriority(uint8_t value, const std::string& versionId)
{
    std::map<std::string, uint8_t> priorityMap;

    // Insert the requested version and priority, it may not exist yet.
    priorityMap.insert(std::make_pair(versionId, value));

    for (const auto& intf : activations)
    {
        if (intf.second->redundancyPriority)
        {
            priorityMap.insert(std::make_pair(
                intf.first, intf.second->redundancyPriority->priority()));
        }
    }

    // Lambda function to compare 2 priority values, use <= to allow duplicates
    typedef std::function<bool(std::pair<std::string, uint8_t>,
                               std::pair<std::string, uint8_t>)>
        cmpPriority;
    cmpPriority cmpPriorityFunc =
        [](const std::pair<std::string, uint8_t>& priority1,
           const std::pair<std::string, uint8_t>& priority2) {
            return priority1.second <= priority2.second;
        };

    // Sort versions by ascending priority
    std::set<std::pair<std::string, uint8_t>, cmpPriority> prioritySet(
        priorityMap.begin(), priorityMap.end(), cmpPriorityFunc);

    auto freePriorityValue = value;
    for (auto& element : prioritySet)
    {
        if (element.first == versionId)
        {
            continue;
        }
        if (element.second == freePriorityValue)
        {
            ++freePriorityValue;
            auto it = activations.find(element.first);
            it->second->redundancyPriority->sdbusPriority(freePriorityValue);
        }
    }

    auto lowestVersion = prioritySet.begin()->first;
    if (value == prioritySet.begin()->second)
    {
        lowestVersion = versionId;
    }
    updateUbootEnvVars(lowestVersion);
}

void ItemUpdater::reset()
{
    phosphor::software::updater::Helper::factoryReset();

    info("BMC factory reset will take effect upon reboot.");
}

void ItemUpdater::removeReadOnlyPartition(const std::string& versionId)
{
    auto flashId = versions.find(versionId)->second->path();
    helper.removeVersion(flashId);
}

bool ItemUpdater::fieldModeEnabled(bool value)
{
    // enabling field mode is intended to be one way: false -> true
    if (value && !control::FieldMode::fieldModeEnabled())
    {
        control::FieldMode::fieldModeEnabled(value);

        auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                          SYSTEMD_INTERFACE, "StartUnit");
        method.append("obmc-flash-bmc-setenv@fieldmode\\x3dtrue.service",
                      "replace");
        bus.call_noreply(method);

        method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                     SYSTEMD_INTERFACE, "StopUnit");
        method.append("usr-local.mount", "replace");
        bus.call_noreply(method);

        std::vector<std::string> usrLocal = {"usr-local.mount"};

        method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                     SYSTEMD_INTERFACE, "MaskUnitFiles");
        method.append(usrLocal, false, true);
        bus.call_noreply(method);
    }
    else if (!value && control::FieldMode::fieldModeEnabled())
    {
        elog<NotAllowed>(xyz::openbmc_project::common::NotAllowed::REASON(
            "FieldMode is not allowed to be cleared"));
    }

    return control::FieldMode::fieldModeEnabled();
}

void ItemUpdater::restoreFieldModeStatus()
{
    // The fieldmode u-boot environment variable may not exist since it is not
    // part of the default environment, run fw_printenv with 2>&1 to ignore the
    // error message in the journal "Error: "fieldmode" not defined"
    std::pair<int, std::string> ret =
        utils::execute("/sbin/fw_printenv", "-n", "fieldmode", "2>&1");

    if (ret.first != 0)
    {
        return;
    }

    // truncate any extra characters off the end to compare against a "true" str
    std::string result = ret.second.substr(0, 4);
    if (result == "true")
    {
        ItemUpdater::fieldModeEnabled(true);
    }
}

void ItemUpdater::setBMCInventoryPath()
{
    auto depth = 0;
    auto mapperCall = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH,
                                          MAPPER_INTERFACE, "GetSubTreePaths");

    mapperCall.append(INVENTORY_PATH);
    mapperCall.append(depth);
    std::vector<std::string> filter = {BMC_INVENTORY_INTERFACE};
    mapperCall.append(filter);

    try
    {
        auto response = bus.call(mapperCall);

        using ObjectPaths = std::vector<std::string>;
        ObjectPaths result;
        response.read(result);

        if (!result.empty())
        {
            bmcInventoryPath = result.front();
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        error("Error in mapper GetSubTreePath: {ERROR}", "ERROR", e);
        return;
    }

    return;
}

void ItemUpdater::createActiveAssociation(const std::string& path)
{
    assocs.emplace_back(
        std::make_tuple(ACTIVE_FWD_ASSOCIATION, ACTIVE_REV_ASSOCIATION, path));
    associations(assocs);
}

void ItemUpdater::createFunctionalAssociation(const std::string& path)
{
    assocs.emplace_back(std::make_tuple(FUNCTIONAL_FWD_ASSOCIATION,
                                        FUNCTIONAL_REV_ASSOCIATION, path));
    associations(assocs);
}

void ItemUpdater::createUpdateableAssociation(const std::string& path)
{
    assocs.emplace_back(std::make_tuple(UPDATEABLE_FWD_ASSOCIATION,
                                        UPDATEABLE_REV_ASSOCIATION, path));
    associations(assocs);
}

void ItemUpdater::removeAssociations(const std::string& path)
{
    for (auto iter = assocs.begin(); iter != assocs.end();)
    {
        if (std::get<2>(*iter) == path)
        {
            iter = assocs.erase(iter);
            associations(assocs);
        }
        else
        {
            ++iter;
        }
    }
}

bool ItemUpdater::isLowestPriority(uint8_t value)
{
    for (const auto& intf : activations)
    {
        if (intf.second->redundancyPriority)
        {
            if (intf.second->redundancyPriority->priority() < value)
            {
                return false;
            }
        }
    }
    return true;
}

void ItemUpdater::updateUbootEnvVars(const std::string& versionId)
{
    auto it = versions.find(versionId);
    if (it == versions.end())
    {
        return;
    }
    auto flashId = it->second->path();
    helper.updateUbootVersionId(flashId);
}

void ItemUpdater::resetUbootEnvVars()
{
    decltype(activations.begin()->second->redundancyPriority->priority())
        lowestPriority = std::numeric_limits<uint8_t>::max();
    decltype(activations.begin()->second->versionId) lowestPriorityVersion;
    for (const auto& intf : activations)
    {
        if (!intf.second->redundancyPriority)
        {
            // Skip this version if the redundancyPriority is not initialized.
            continue;
        }

        if (intf.second->redundancyPriority->priority() <= lowestPriority)
        {
            lowestPriority = intf.second->redundancyPriority->priority();
            lowestPriorityVersion = intf.second->versionId;
        }
    }

    // Update the U-boot environment variable to point to the lowest priority
    updateUbootEnvVars(lowestPriorityVersion);
}

void ItemUpdater::freeSpace([[maybe_unused]] const Activation& caller)
{
#ifdef BMC_STATIC_DUAL_IMAGE
    // For the golden image case, always remove the version on the primary side
    std::string versionIDtoErase;
    for (const auto& iter : activations)
    {
        if (iter.second->redundancyPriority &&
            iter.second->redundancyPriority->priority() == 0)
        {
            versionIDtoErase = iter.second->versionId;
            break;
        }
    }
    if (!versionIDtoErase.empty())
    {
        erase(versionIDtoErase);
    }
    else
    {
        warning("Failed to find version to erase");
    }
#else
    //  Versions with the highest priority in front
    std::priority_queue<std::pair<int, std::string>,
                        std::vector<std::pair<int, std::string>>,
                        std::less<std::pair<int, std::string>>>
        versionsPQ;

    std::size_t count = 0;
    for (const auto& iter : activations)
    {
        if ((iter.second.get()->activation() ==
             server::Activation::Activations::Active) ||
            (iter.second.get()->activation() ==
             server::Activation::Activations::Failed))
        {
            count++;
            // Don't put the functional version on the queue since we can't
            // remove the "running" BMC version.
            // If ACTIVE_BMC_MAX_ALLOWED <= 1, there is only one active BMC,
            // so remove functional version as well.
            // Don't delete the the Activation object that called this function.
            if ((versions.find(iter.second->versionId)
                     ->second->isFunctional() &&
                 ACTIVE_BMC_MAX_ALLOWED > 1) ||
                (iter.second->versionId == caller.versionId))
            {
                continue;
            }

            // Failed activations don't have priority, assign them a large value
            // for sorting purposes.
            auto priority = 999;
            if (iter.second.get()->activation() ==
                    server::Activation::Activations::Active &&
                iter.second->redundancyPriority)
            {
                priority = iter.second->redundancyPriority.get()->priority();
            }

            versionsPQ.push(std::make_pair(priority, iter.second->versionId));
        }
    }

    // If the number of BMC versions is over ACTIVE_BMC_MAX_ALLOWED -1,
    // remove the highest priority one(s).
    while ((count >= ACTIVE_BMC_MAX_ALLOWED) && (!versionsPQ.empty()))
    {
        erase(versionsPQ.top().second);
        versionsPQ.pop();
        count--;
    }
#endif
}

void ItemUpdater::mirrorUbootToAlt()
{
    helper.mirrorAlt();
}

bool ItemUpdater::checkImage(const std::string& filePath,
                             const std::vector<std::string>& imageList)
{
    bool valid = true;

    for (auto& bmcImage : imageList)
    {
        fs::path file(filePath);
        file /= bmcImage;
        std::ifstream efile(file.c_str());
        if (efile.good() != 1)
        {
            valid = false;
            break;
        }
    }

    return valid;
}

#ifdef HOST_BIOS_UPGRADE
void ItemUpdater::createBIOSObject()
{
    std::string path = BIOS_OBJPATH;
    // Get version id from last item in the path
    auto pos = path.rfind('/');
    if (pos == std::string::npos)
    {
        error("No version id found in object path {PATH}", "PATH", path);
        return;
    }

    createActiveAssociation(path);
    createFunctionalAssociation(path);
    createUpdateableAssociation(path);

    auto versionId = path.substr(pos + 1);
    auto version = "null";
    AssociationList assocs;
    biosActivation = std::make_unique<Activation>(
        bus, path, *this, versionId, server::Activation::Activations::Active,
        assocs);
    auto dummyErase = [](const std::string& /*entryId*/) {
        // Do nothing;
    };
    biosVersion = std::make_unique<VersionClass>(
        bus, path, version, VersionPurpose::Host, "", "",
        std::vector<std::string>(),
        std::bind(dummyErase, std::placeholders::_1), "");
    biosVersion->deleteObject =
        std::make_unique<phosphor::software::manager::Delete>(
            bus, path, *biosVersion);

    if (useUpdateDBusInterface)
    {
        createUpdateObject(versionId, path);
    }
}
#endif

void ItemUpdater::getRunningSlot()
{
    // Check /run/media/slot to get the slot number
    constexpr auto slotFile = "/run/media/slot";
    std::fstream f(slotFile, std::ios_base::in);
    f >> runningImageSlot;
}

} // namespace updater
} // namespace software
} // namespace phosphor
