#include "config.h"

#include "item_updater_ubi.hpp"

#include "activation_ubi.hpp"
#include "serialize.hpp"
#include "utils.hpp"
#include "version.hpp"
#include "xyz/openbmc_project/Common/error.hpp"

#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <xyz/openbmc_project/Software/Version/server.hpp>

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

namespace openpower
{
namespace software
{
namespace updater
{

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

using namespace sdbusplus::xyz::openbmc_project::Common::Error;
using namespace phosphor::logging;

std::unique_ptr<Activation> ItemUpdaterUbi::createActivationObject(
    const std::string& path, const std::string& versionId,
    const std::string& extVersion,
    sdbusplus::xyz::openbmc_project::Software::server::Activation::Activations
        activationStatus,
    AssociationList& assocs)
{
    return std::make_unique<ActivationUbi>(
        bus, path, *this, versionId, extVersion, activationStatus, assocs);
}

std::unique_ptr<Version> ItemUpdaterUbi::createVersionObject(
    const std::string& objPath, const std::string& versionId,
    const std::string& versionString,
    sdbusplus::xyz::openbmc_project::Software::server::Version::VersionPurpose
        versionPurpose,
    const std::string& filePath)
{
    auto version = std::make_unique<Version>(
        bus, objPath, *this, versionId, versionString, versionPurpose, filePath,
        std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1));
    version->deleteObject = std::make_unique<Delete>(bus, objPath, *version);
    return version;
}

bool ItemUpdaterUbi::validateImage(const std::string& path)
{
    return validateSquashFSImage(path) == 0;
}

void ItemUpdaterUbi::processPNORImage()
{
    // Read pnor.toc from folders under /media/
    // to get Active Software Versions.
    for (const auto& iter : std::filesystem::directory_iterator(MEDIA_DIR))
    {
        auto activationState = server::Activation::Activations::Active;

        static const auto PNOR_RO_PREFIX_LEN = strlen(PNOR_RO_PREFIX);
        static const auto PNOR_RW_PREFIX_LEN = strlen(PNOR_RW_PREFIX);

        // Check if the PNOR_RO_PREFIX is the prefix of the iter.path
        if (0 ==
            iter.path().native().compare(0, PNOR_RO_PREFIX_LEN, PNOR_RO_PREFIX))
        {
            // The versionId is extracted from the path
            // for example /media/pnor-ro-2a1022fe.
            auto id = iter.path().native().substr(PNOR_RO_PREFIX_LEN);
            auto pnorTOC = iter.path() / PNOR_TOC_FILE;
            if (!std::filesystem::is_regular_file(pnorTOC))
            {
                log<level::ERR>("Failed to read pnorTOC.",
                                entry("FILENAME=%s", pnorTOC.c_str()));
                ItemUpdaterUbi::erase(id);
                continue;
            }
            auto keyValues = Version::getValue(
                pnorTOC, {{"version", ""}, {"extended_version", ""}});
            auto& version = keyValues.at("version");
            if (version.empty())
            {
                log<level::ERR>("Failed to read version from pnorTOC",
                                entry("FILENAME=%s", pnorTOC.c_str()));
                activationState = server::Activation::Activations::Invalid;
            }

            auto& extendedVersion = keyValues.at("extended_version");
            if (extendedVersion.empty())
            {
                log<level::ERR>("Failed to read extendedVersion from pnorTOC",
                                entry("FILENAME=%s", pnorTOC.c_str()));
                activationState = server::Activation::Activations::Invalid;
            }

            auto purpose = server::Version::VersionPurpose::Host;
            auto path = std::filesystem::path(SOFTWARE_OBJPATH) / id;
            AssociationList associations = {};

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

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

            // All updateable firmware components must expose the updateable
            // association.
            createUpdateableAssociation(path);

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

            // If Active, create RedundancyPriority instance for this version.
            if (activationState == server::Activation::Activations::Active)
            {
                uint8_t priority = std::numeric_limits<uint8_t>::max();
                if (!restoreFromFile(id, priority))
                {
                    log<level::ERR>("Unable to restore priority from file.",
                                    entry("VERSIONID=%s", id.c_str()));
                }
                activations.find(id)->second->redundancyPriority =
                    std::make_unique<RedundancyPriorityUbi>(
                        bus, path, *(activations.find(id)->second), priority);
            }

            // Create Version instance for this version.
            auto versionPtr = std::make_unique<Version>(
                bus, path, *this, id, version, purpose, "",
                std::bind(&ItemUpdaterUbi::erase, this, std::placeholders::_1));
            versionPtr->deleteObject = std::make_unique<Delete>(bus, path,
                                                                *versionPtr);
            versions.insert(std::make_pair(id, std::move(versionPtr)));
        }
        else if (0 == iter.path().native().compare(0, PNOR_RW_PREFIX_LEN,
                                                   PNOR_RW_PREFIX))
        {
            auto id = iter.path().native().substr(PNOR_RW_PREFIX_LEN);
            auto roDir = PNOR_RO_PREFIX + id;
            if (!std::filesystem::is_directory(roDir))
            {
                log<level::ERR>("No corresponding read-only volume found.",
                                entry("DIRNAME=%s", roDir.c_str()));
                ItemUpdaterUbi::erase(id);
            }
        }
    }

    // Look at the RO symlink to determine if there is a functional image
    auto id = determineId(PNOR_RO_ACTIVE_PATH);
    if (!id.empty())
    {
        updateFunctionalAssociation(id);
    }
    return;
}

int ItemUpdaterUbi::validateSquashFSImage(const std::string& filePath)
{
    auto file = std::filesystem::path(filePath) / squashFSImage;
    if (std::filesystem::is_regular_file(file))
    {
        return 0;
    }
    else
    {
        log<level::ERR>("Failed to find the SquashFS image.");
        return -1;
    }
}

void ItemUpdaterUbi::removeReadOnlyPartition(const std::string& versionId)
{
    auto serviceFile = "obmc-flash-bios-ubiumount-ro@" + versionId + ".service";

    // Remove the read-only partitions.
    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append(serviceFile, "replace");
    bus.call_noreply(method);
}

void ItemUpdaterUbi::removeReadWritePartition(const std::string& versionId)
{
    auto serviceFile = "obmc-flash-bios-ubiumount-rw@" + versionId + ".service";

    // Remove the read-write partitions.
    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append(serviceFile, "replace");
    bus.call_noreply(method);
}

void ItemUpdaterUbi::reset()
{
    utils::hiomapdSuspend(bus);

    constexpr static auto patchDir = "/usr/local/share/pnor";
    if (std::filesystem::is_directory(patchDir))
    {
        for (const auto& iter : std::filesystem::directory_iterator(patchDir))
        {
            std::filesystem::remove_all(iter);
        }
    }

    // Clear the read-write partitions.
    for (const auto& it : activations)
    {
        auto rwDir = PNOR_RW_PREFIX + it.first;
        if (std::filesystem::is_directory(rwDir))
        {
            for (const auto& iter : std::filesystem::directory_iterator(rwDir))
            {
                std::filesystem::remove_all(iter);
            }
        }
    }

    // Clear the preserved partition, except for SECBOOT that contains keys
    // provisioned for the system.
    if (std::filesystem::is_directory(PNOR_PRSV))
    {
        for (const auto& iter : std::filesystem::directory_iterator(PNOR_PRSV))
        {
            auto secbootPartition = "SECBOOT";
            if (iter.path().stem() == secbootPartition)
            {
                continue;
            }
            std::filesystem::remove_all(iter);
        }
    }

    utils::hiomapdResume(bus);
}

bool ItemUpdaterUbi::isVersionFunctional(const std::string& versionId)
{
    if (!std::filesystem::exists(PNOR_RO_ACTIVE_PATH))
    {
        return false;
    }

    std::filesystem::path activeRO =
        std::filesystem::read_symlink(PNOR_RO_ACTIVE_PATH);

    if (!std::filesystem::is_directory(activeRO))
    {
        return false;
    }

    if (activeRO.string().find(versionId) == std::string::npos)
    {
        return false;
    }

    // active PNOR is the version we're checking
    return true;
}

void ItemUpdaterUbi::freePriority(uint8_t value, const std::string& versionId)
{
    //  Versions with the lowest priority in front
    std::priority_queue<std::pair<int, std::string>,
                        std::vector<std::pair<int, std::string>>,
                        std::greater<std::pair<int, std::string>>>
        versionsPQ;

    for (const auto& intf : activations)
    {
        if (intf.second->redundancyPriority)
        {
            versionsPQ.push(std::make_pair(
                intf.second->redundancyPriority.get()->priority(),
                intf.second->versionId));
        }
    }

    while (!versionsPQ.empty())
    {
        if (versionsPQ.top().first == value &&
            versionsPQ.top().second != versionId)
        {
            // Increase priority by 1 and update its value
            ++value;
            storeToFile(versionsPQ.top().second, value);
            auto it = activations.find(versionsPQ.top().second);
            it->second->redundancyPriority.get()->sdbusplus::xyz::
                openbmc_project::Software::server::RedundancyPriority::priority(
                    value);
        }
        versionsPQ.pop();
    }
}

bool ItemUpdaterUbi::erase(std::string entryId)
{
    if (!ItemUpdater::erase(entryId))
    {
        return false;
    }

    // Remove priority persistence file
    removeFile(entryId);

    // Removing read-only and read-write partitions
    removeReadWritePartition(entryId);
    removeReadOnlyPartition(entryId);

    return true;
}

void ItemUpdaterUbi::deleteAll()
{
    auto chassisOn = isChassisOn();

    for (const auto& activationIt : activations)
    {
        if (isVersionFunctional(activationIt.first) && chassisOn)
        {
            continue;
        }
        else
        {
            ItemUpdaterUbi::erase(activationIt.first);
        }
    }

    // Remove any remaining pnor-ro- or pnor-rw- volumes that do not match
    // the current version.
    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append("obmc-flash-bios-cleanup.service", "replace");
    bus.call_noreply(method);
}

// TODO: openbmc/openbmc#1402 Monitor flash usage
bool ItemUpdaterUbi::freeSpace()
{
    bool isSpaceFreed = false;
    //  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)
        {
            count++;
            // Don't put the functional version on the queue since we can't
            // remove the "running" PNOR version if it allows multiple PNORs
            // But removing functional version if there is only one PNOR.
            if (ACTIVE_PNOR_MAX_ALLOWED > 1 &&
                isVersionFunctional(iter.second->versionId))
            {
                continue;
            }
            versionsPQ.push(std::make_pair(
                iter.second->redundancyPriority.get()->priority(),
                iter.second->versionId));
        }
    }

    // If the number of PNOR versions is over ACTIVE_PNOR_MAX_ALLOWED -1,
    // remove the highest priority one(s).
    while ((count >= ACTIVE_PNOR_MAX_ALLOWED) && (!versionsPQ.empty()))
    {
        erase(versionsPQ.top().second);
        versionsPQ.pop();
        count--;
        isSpaceFreed = true;
    }
    return isSpaceFreed;
}

std::string ItemUpdaterUbi::determineId(const std::string& symlinkPath)
{
    if (!std::filesystem::exists(symlinkPath))
    {
        return {};
    }

    auto target = std::filesystem::canonical(symlinkPath).string();

    // check to make sure the target really exists
    if (!std::filesystem::is_regular_file(target + "/" + PNOR_TOC_FILE))
    {
        return {};
    }
    // Get the image <id> from the symlink target
    // for example /media/ro-2a1022fe
    static const auto PNOR_RO_PREFIX_LEN = strlen(PNOR_RO_PREFIX);
    return target.substr(PNOR_RO_PREFIX_LEN);
}

void GardResetUbi::reset()
{
    // The GUARD partition is currently misspelled "GUARD." This file path will
    // need to be updated in the future.
    auto path = std::filesystem::path(PNOR_PRSV_ACTIVE_PATH);
    path /= "GUARD";

    utils::hiomapdSuspend(bus);

    if (std::filesystem::is_regular_file(path))
    {
        std::filesystem::remove(path);
    }

    utils::hiomapdResume(bus);
}

} // namespace updater
} // namespace software
} // namespace openpower
