#include "config.h"

#include "item_updater_mmc.hpp"

#include "activation_mmc.hpp"
#include "utils.hpp"
#include "version.hpp"

#include <phosphor-logging/log.hpp>

#include <filesystem>
#include <format>
#include <iostream>
#include <thread>

namespace openpower
{
namespace software
{
namespace updater
{

using ::phosphor::logging::level;
using ::phosphor::logging::log;
// These functions are just a stub (empty) because the current eMMC
// implementation uses the BMC updater (repo phosphor-bmc-code-mgmt) to write
// the new host FW to flash since it's delivered as a "System" image in the
// same BMC tarball as the BMC image.

std::unique_ptr<Activation> ItemUpdaterMMC::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<ActivationMMC>(
        bus, path, *this, versionId, extVersion, activationStatus, assocs);
}

std::unique_ptr<Version> ItemUpdaterMMC::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(&ItemUpdaterMMC::erase, this, std::placeholders::_1));
    version->deleteObject = std::make_unique<Delete>(bus, objPath, *version);
    return version;
}

bool ItemUpdaterMMC::validateImage(const std::string&)
{
    return true;
}

void ItemUpdaterMMC::processPNORImage() {}

void ItemUpdaterMMC::reset()
{
    // Do not reset read-only files needed for reset or ext4 default files
    const std::vector<std::string> exclusionList = {
        "alternate",  "hostfw-a", "hostfw-b",
        "lost+found", "nvram",    "running-ro"};
    std::filesystem::path dirPath(std::string(MEDIA_DIR "hostfw/"));
    // Delete all files in /media/hostfw/ except for those on exclusionList
    for (const auto& p : std::filesystem::directory_iterator(dirPath))
    {
        if (std::find(exclusionList.begin(), exclusionList.end(),
                      p.path().stem().string()) == exclusionList.end())
        {
            std::filesystem::remove_all(p);
        }
    }

    // Delete all BMC error logs to avoid discrepancies with the host error logs
    utils::deleteAllErrorLogs(bus);

    // Set attribute to clear hypervisor NVRAM
    utils::setClearNvram(bus);

    // reset the enabled property of dimms/cpu after factory reset
    gardReset->reset();

    // Remove files related to the Hardware Management Console / BMC web app
    utils::clearHMCManaged(bus);
    std::filesystem::path consolePath("/var/lib/bmcweb/ibm-management-console");
    if (std::filesystem::exists(consolePath))
    {
        std::filesystem::remove_all(consolePath);
    }
    std::filesystem::path bmcdataPath("/home/root/bmcweb_persistent_data.json");
    if (std::filesystem::exists(bmcdataPath))
    {
        std::filesystem::remove(bmcdataPath);
    }

    // Recreate default files.
    // std::tuple<method, service_name>
    const std::tuple<std::string, std::string> services[] = {
        {"StartUnit", "obmc-flash-bios-init.service"},
        {"StartUnit", "obmc-flash-bios-patch.service"},
        {"StartUnit", "openpower-process-host-firmware.service"},
        {"StartUnit", "openpower-update-bios-attr-table.service"},
        {"RestartUnit", "org.open_power.HardwareIsolation.service"}};

    for (const auto& service : services)
    {
        auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                          SYSTEMD_INTERFACE,
                                          std::get<0>(service).c_str());
        method.append(std::get<1>(service), "replace");
        // Ignore errors if the service is not found - not all systems
        // may have these services
        try
        {
            bus.call_noreply(method);
        }
        catch (const std::exception& e)
        {}
    }

    // Wait a few seconds for the service files and reset operations to finish,
    // otherwise the BMC may be rebooted and cause corruption.
    constexpr auto resetWait = std::chrono::seconds(5);
    std::this_thread::sleep_for(resetWait);
}

bool ItemUpdaterMMC::isVersionFunctional(const std::string& versionId)
{
    return versionId == functionalVersionId;
}

void ItemUpdaterMMC::freePriority(uint8_t, const std::string&) {}

void ItemUpdaterMMC::deleteAll() {}

bool ItemUpdaterMMC::freeSpace()
{
    return true;
}

void ItemUpdaterMMC::updateFunctionalAssociation(const std::string&) {}
void GardResetMMC::enableInventoryItems()
{
    (void)enableInventoryItemsHelper(
        "xyz.openbmc_project.PLDM",
        "xyz.openbmc_project.Inventory.Item.CpuCore",
        "/xyz/openbmc_project/inventory/system/chassis/motherboard");

    (void)enableInventoryItemsHelper("xyz.openbmc_project.Inventory.Manager",
                                     "xyz.openbmc_project.Inventory.Item.Dimm",
                                     "/xyz/openbmc_project/inventory");
}

void GardResetMMC::enableInventoryItemsHelper(const std::string& service,
                                              const std::string& intf,
                                              const std::string& objPath)
{
    const std::vector<std::string> intflist{intf};

    std::vector<std::string> objs;
    try
    {
        auto mapperCall = bus.new_method_call(
            "xyz.openbmc_project.ObjectMapper",
            "/xyz/openbmc_project/object_mapper",
            "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths");
        mapperCall.append(objPath);
        mapperCall.append(0);
        mapperCall.append(intflist);

        auto response = bus.call(mapperCall);
        response.read(objs);
        for (auto& obj : objs)
        {
            auto method =
                bus.new_method_call(service.c_str(), obj.c_str(),
                                    "org.freedesktop.DBus.Properties", "Set");
            std::variant<bool> propertyVal{true};
            method.append("xyz.openbmc_project.Object.Enable", "Enabled",
                          propertyVal);
            bus.call_noreply(method);
        }
    }
    catch (const sdbusplus::exception_t& e)
    {
        log<level::ERR>(
            std::format("Failed to enable specified inventory items ex({}) "
                        "intf({}) objpath({})",
                        e.what(), intf, objPath)
                .c_str());
    }
}

void GardResetMMC::reset()
{
    log<level::INFO>("GardResetMMC::reset");
    (void)enableInventoryItems();
}

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