#include "update_manager.hpp"

#include "item_updater.hpp"
#include "software_utils.hpp"
#include "version.hpp"

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

#include <filesystem>

PHOSPHOR_LOG2_USING;

namespace phosphor::software::update
{

namespace fs = std::filesystem;
namespace softwareUtils = phosphor::software::utils;
namespace SoftwareLogging = phosphor::logging::xyz::openbmc_project::software;
namespace SoftwareErrors =
    sdbusplus::error::xyz::openbmc_project::software::image;
using namespace phosphor::logging;
using Version = phosphor::software::manager::Version;
using ActivationIntf = phosphor::software::updater::Activation;
using ManifestFail = SoftwareLogging::image::ManifestFileFailure;
using UnTarFail = SoftwareLogging::image::UnTarFailure;
using InternalFail = SoftwareLogging::image::InternalFailure;
using ImageFail = SoftwareLogging::image::ImageFailure;

void Manager::processImageFailed(sdbusplus::message::unix_fd image,
                                 std::string& id)
{
    close(image);
    updateInProgress = false;
    itemUpdater.updateActivationStatus(id,
                                       ActivationIntf::Activations::Invalid);
}

bool verifyImagePurpose(Version::VersionPurpose purpose,
                        ItemUpdaterIntf::UpdaterType type)
{
    if (purpose == Version::VersionPurpose::Host)
    {
        return (type == ItemUpdaterIntf::UpdaterType::BIOS ||
                type == ItemUpdaterIntf::UpdaterType::ALL);
    }
    return true;
}

auto Manager::processImage(sdbusplus::message::unix_fd image,
                           ApplyTimeIntf::RequestedApplyTimes applyTime,
                           std::string id, std::string objPath)
    -> sdbusplus::async::task<>
{
    debug("Processing image {FD}", "FD", image.fd);
    fs::path tmpDirPath(std::string{IMG_UPLOAD_DIR});
    tmpDirPath /= "imageXXXXXX";
    auto tmpDir = tmpDirPath.string();
    // Create a tmp dir to copy tarball.
    if (!mkdtemp(tmpDir.data()))
    {
        error("Error ({ERRNO}) occurred during mkdtemp", "ERRNO", errno);
        processImageFailed(image, id);
        report<SoftwareErrors::InternalFailure>(InternalFail::FAIL("mkdtemp"));
        co_return;
    }

    std::error_code ec;
    tmpDirPath = tmpDir;
    softwareUtils::RemovablePath tmpDirToRemove(tmpDirPath);

    // Untar tarball into the tmp dir
    if (!softwareUtils::unTar(image, tmpDirPath.string()))
    {
        error("Error occurred during untar");
        processImageFailed(image, id);
        report<SoftwareErrors::UnTarFailure>(
            UnTarFail::PATH(tmpDirPath.c_str()));
        co_return;
    }

    fs::path manifestPath = tmpDirPath;
    manifestPath /= MANIFEST_FILE_NAME;

    // Get version
    auto version = Version::getValue(manifestPath.string(), "version");
    if (version.empty())
    {
        error("Unable to read version from manifest file");
        processImageFailed(image, id);
        report<SoftwareErrors::ManifestFileFailure>(
            ManifestFail::PATH(manifestPath.string().c_str()));
        co_return;
    }

    // Get running machine name
    std::string currMachine = Version::getBMCMachine(OS_RELEASE_FILE);
    if (currMachine.empty())
    {
        auto path = OS_RELEASE_FILE;
        error("Failed to read machine name from osRelease: {PATH}", "PATH",
              path);
        processImageFailed(image, id);
        report<SoftwareErrors::ImageFailure>(
            ImageFail::FAIL("Failed to read machine name"),
            ImageFail::PATH(path));
        co_return;
    }

    // Get machine name for image to be upgraded
    std::string machineStr =
        Version::getValue(manifestPath.string(), "MachineName");
    if (!machineStr.empty())
    {
        if (machineStr != currMachine)
        {
            error(
                "BMC upgrade: Machine name doesn't match: {CURRENT_MACHINE} vs {NEW_MACHINE}",
                "CURRENT_MACHINE", currMachine, "NEW_MACHINE", machineStr);
            processImageFailed(image, id);
            report<SoftwareErrors::ImageFailure>(
                ImageFail::FAIL("Machine name does not match"),
                ImageFail::PATH(manifestPath.string().c_str()));
            co_return;
        }
    }
    else
    {
        warning("No machine name in Manifest file");
        report<SoftwareErrors::ImageFailure>(
            ImageFail::FAIL("MANIFEST is missing machine name"),
            ImageFail::PATH(manifestPath.string().c_str()));
    }

    // Get purpose
    auto purposeString = Version::getValue(manifestPath.string(), "purpose");
    if (purposeString.empty())
    {
        error("Unable to read purpose from manifest file");
        processImageFailed(image, id);
        report<SoftwareErrors::ManifestFileFailure>(
            ManifestFail::PATH(manifestPath.string().c_str()));
        co_return;
    }
    auto convertedPurpose =
        sdbusplus::message::convert_from_string<Version::VersionPurpose>(
            purposeString);
    if (!convertedPurpose)
    {
        warning(
            "Failed to convert manifest purpose ({PURPOSE}) to enum; setting to Unknown.",
            "PURPOSE", purposeString);
    }
    auto purpose = convertedPurpose.value_or(Version::VersionPurpose::Unknown);

    if (!verifyImagePurpose(purpose, itemUpdater.type))
    {
        error("Purpose ({PURPOSE}) is not supported", "PURPOSE", purpose);
        processImageFailed(image, id);
        report<SoftwareErrors::ImageFailure>(
            ImageFail::FAIL("Purpose is not supported"),
            ImageFail::PATH(manifestPath.string().c_str()));
        co_return;
    }

    // Get ExtendedVersion
    std::string extendedVersion =
        Version::getValue(manifestPath.string(), "ExtendedVersion");

    // Get CompatibleNames
    std::vector<std::string> compatibleNames =
        Version::getRepeatedValues(manifestPath.string(), "CompatibleName");

    // Rename IMG_UPLOAD_DIR/imageXXXXXX to IMG_UPLOAD_DIR/id as Manifest
    // parsing succedded.
    fs::path imageDirPath = std::string{IMG_UPLOAD_DIR};
    imageDirPath /= id;
    fs::rename(tmpDirPath, imageDirPath, ec);
    tmpDirToRemove.path.clear();

    auto filePath = imageDirPath.string();
    // Create Version object
    auto state = itemUpdater.verifyAndCreateObjects(
        id, objPath, version, purpose, extendedVersion, filePath,
        compatibleNames);
    if (state != ActivationIntf::Activations::Ready)
    {
        error("Software image is invalid");
        processImageFailed(image, id);
        report<SoftwareErrors::ImageFailure>(
            ImageFail::FAIL("Image is invalid"),
            ImageFail::PATH(filePath.c_str()));
        co_return;
    }
    if (applyTime == ApplyTimeIntf::RequestedApplyTimes::Immediate ||
        applyTime == ApplyTimeIntf::RequestedApplyTimes::OnReset)
    {
        itemUpdater.requestActivation(id);
    }

    updateInProgress = false;
    close(image);
    co_return;
}

sdbusplus::message::object_path Manager::startUpdate(
    sdbusplus::message::unix_fd image,
    ApplyTimeIntf::RequestedApplyTimes applyTime)
{
    info("Starting update for image {FD}", "FD", static_cast<int>(image));
    using sdbusplus::xyz::openbmc_project::Common::Error::Unavailable;
    if (updateInProgress)
    {
        error("Failed to start as update is already in progress");
        report<Unavailable>();
        return sdbusplus::message::object_path();
    }
    updateInProgress = true;

    auto id = Version::getId(std::to_string(randomGen()));
    auto objPath = std::string{SOFTWARE_OBJPATH} + '/' + id;

    // Create Activation Object
    itemUpdater.createActivationWithApplyTime(id, objPath, applyTime);

    int newFd = dup(image);
    ctx.spawn(processImage(newFd, applyTime, id, objPath));

    return sdbusplus::message::object_path(objPath);
}

} // namespace phosphor::software::update
