#include "config.h"

#include "activation.hpp"

#include "utils.hpp"

#include <cassert>
#include <filesystem>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>

namespace phosphor
{
namespace software
{
namespace updater
{

constexpr auto SYSTEMD_BUSNAME = "org.freedesktop.systemd1";
constexpr auto SYSTEMD_PATH = "/org/freedesktop/systemd1";
constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";

namespace fs = std::filesystem;
namespace softwareServer = sdbusplus::xyz::openbmc_project::Software::server;

using namespace phosphor::logging;
using SoftwareActivation = softwareServer::Activation;

auto Activation::activation(Activations value) -> Activations
{
    if (value == Status::Activating)
    {
        value = startActivation();
    }
    else
    {
        activationBlocksTransition.reset();
        activationProgress.reset();
    }

    return SoftwareActivation::activation(value);
}

auto Activation::requestedActivation(RequestedActivations value)
    -> RequestedActivations
{
    if ((value == SoftwareActivation::RequestedActivations::Active) &&
        (SoftwareActivation::requestedActivation() !=
         SoftwareActivation::RequestedActivations::Active))
    {
        // PSU image could be activated even when it's in active,
        // e.g. in case a PSU is replaced and has a older image, it will be
        // updated with the running PSU image that is stored in BMC.
        if ((activation() == Status::Ready) ||
            (activation() == Status::Failed) || activation() == Status::Active)
        {
            activation(Status::Activating);
        }
    }
    return SoftwareActivation::requestedActivation(value);
}

void Activation::unitStateChange(sdbusplus::message::message& msg)
{
    uint32_t newStateID{};
    sdbusplus::message::object_path newStateObjPath;
    std::string newStateUnit{};
    std::string newStateResult{};

    // Read the msg and populate each variable
    msg.read(newStateID, newStateObjPath, newStateUnit, newStateResult);

    if (newStateUnit == psuUpdateUnit)
    {
        if (newStateResult == "done")
        {
            onUpdateDone();
        }
        if (newStateResult == "failed" || newStateResult == "dependency")
        {
            onUpdateFailed();
        }
    }
}

bool Activation::doUpdate(const std::string& psuInventoryPath)
{
    currentUpdatingPsu = psuInventoryPath;
    psuUpdateUnit = getUpdateService(currentUpdatingPsu);
    try
    {
        auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                          SYSTEMD_INTERFACE, "StartUnit");
        method.append(psuUpdateUnit, "replace");
        bus.call_noreply(method);
        return true;
    }
    catch (const sdbusplus::exception::exception& e)
    {
        log<level::ERR>("Error staring service", entry("ERROR=%s", e.what()));
        onUpdateFailed();
        return false;
    }
}

bool Activation::doUpdate()
{
    // When the queue is empty, all updates are done
    if (psuQueue.empty())
    {
        finishActivation();
        return true;
    }

    // Do the update on a PSU
    const auto& psu = psuQueue.front();
    return doUpdate(psu);
}

void Activation::onUpdateDone()
{
    auto progress = activationProgress->progress() + progressStep;
    activationProgress->progress(progress);

    // Update the activation association
    auto assocs = associations();
    assocs.emplace_back(ACTIVATION_FWD_ASSOCIATION, ACTIVATION_REV_ASSOCIATION,
                        currentUpdatingPsu);
    associations(assocs);

    activationListener->onUpdateDone(versionId, currentUpdatingPsu);
    currentUpdatingPsu.clear();

    psuQueue.pop();
    doUpdate(); // Update the next psu
}

void Activation::onUpdateFailed()
{
    // TODO: report an event
    log<level::ERR>("Failed to udpate PSU",
                    entry("PSU=%s", psuQueue.front().c_str()));
    std::queue<std::string>().swap(psuQueue); // Clear the queue
    activation(Status::Failed);
}

Activation::Status Activation::startActivation()
{
    // Check if the activation has file path
    if (path().empty())
    {
        log<level::WARNING>("No image for the activation, skipped",
                            entry("VERSION_ID=%s", versionId.c_str()));
        return activation(); // Return the previous activation status
    }

    auto psuPaths = utils::getPSUInventoryPath(bus);
    if (psuPaths.empty())
    {
        log<level::WARNING>("No PSU inventory found");
        return Status::Failed;
    }

    for (const auto& p : psuPaths)
    {
        if (isCompatible(p))
        {
            if (utils::isAssociated(p, associations()))
            {
                log<level::NOTICE>("PSU already running the image, skipping",
                                   entry("PSU=%s", p.c_str()));
                continue;
            }
            psuQueue.push(p);
        }
        else
        {
            log<level::NOTICE>("PSU not compatible",
                               entry("PSU=%s", p.c_str()));
        }
    }

    if (psuQueue.empty())
    {
        log<level::WARNING>("No PSU compatible with the software");
        return activation(); // Return the previous activation status
    }

    if (!activationProgress)
    {
        activationProgress = std::make_unique<ActivationProgress>(bus, objPath);
    }
    if (!activationBlocksTransition)
    {
        activationBlocksTransition =
            std::make_unique<ActivationBlocksTransition>(bus, objPath);
    }

    // The progress to be increased for each successful update of PSU
    // E.g. in case we have 4 PSUs:
    //   1. Initial progrss is 10
    //   2. Add 20 after each update is done, so we will see progress to be 30,
    //      50, 70, 90
    //   3. When all PSUs are updated, it will be 100 and the interface is
    //   removed.
    progressStep = 80 / psuQueue.size();
    if (doUpdate())
    {
        activationProgress->progress(10);
        return Status::Activating;
    }
    else
    {
        return Status::Failed;
    }
}

void Activation::finishActivation()
{
    storeImage();
    activationProgress->progress(100);

    deleteImageManagerObject();

    associationInterface->createActiveAssociation(objPath);
    associationInterface->addFunctionalAssociation(objPath);
    associationInterface->addUpdateableAssociation(objPath);

    // Reset RequestedActivations to none so that it could be activated in
    // future
    requestedActivation(SoftwareActivation::RequestedActivations::None);
    activation(Status::Active);
}

void Activation::deleteImageManagerObject()
{
    // Get the Delete object for <versionID> inside image_manager
    constexpr auto versionServiceStr = "xyz.openbmc_project.Software.Version";
    constexpr auto deleteInterface = "xyz.openbmc_project.Object.Delete";
    std::string versionService;
    auto services = utils::getServices(bus, objPath.c_str(), deleteInterface);

    // We need to find the phosphor-version-software-manager's version service
    // to invoke the delete interface
    for (const auto& service : services)
    {
        if (service.find(versionServiceStr) != std::string::npos)
        {
            versionService = service;
            break;
        }
    }
    if (versionService.empty())
    {
        // When updating a stored image, there is no version object created by
        // "xyz.openbmc_project.Software.Version" service, so skip it.
        return;
    }

    // Call the Delete object for <versionID> inside image_manager
    auto method = bus.new_method_call(versionService.c_str(), objPath.c_str(),
                                      deleteInterface, "Delete");
    try
    {
        bus.call(method);
    }
    catch (const sdbusplus::exception::exception& e)
    {
        log<level::ERR>("Error performing call to Delete object path",
                        entry("ERROR=%s", e.what()),
                        entry("PATH=%s", objPath.c_str()));
    }
}

bool Activation::isCompatible(const std::string& psuInventoryPath)
{
    auto service =
        utils::getService(bus, psuInventoryPath.c_str(), ASSET_IFACE);
    auto psuManufacturer = utils::getProperty<std::string>(
        bus, service.c_str(), psuInventoryPath.c_str(), ASSET_IFACE,
        MANUFACTURER);
    auto psuModel = utils::getProperty<std::string>(
        bus, service.c_str(), psuInventoryPath.c_str(), ASSET_IFACE, MODEL);
    if (psuModel != model)
    {
        // The model shall match
        return false;
    }
    if (!psuManufacturer.empty())
    {
        // If PSU inventory has manufacturer property, it shall match
        return psuManufacturer == manufacturer;
    }
    return true;
}

void Activation::storeImage()
{
    // Store image in persistent dir separated by model
    // and only store the latest one by removing old ones
    auto src = path();
    auto dst = fs::path(IMG_DIR_PERSIST) / model;
    if (src == dst)
    {
        // This happens when updating an stored image, no need to store it again
        return;
    }
    try
    {
        fs::remove_all(dst);
        fs::create_directories(dst);
        fs::copy(src, dst);
        path(dst.string()); // Update the FilePath interface
    }
    catch (const fs::filesystem_error& e)
    {
        log<level::ERR>("Error storing PSU image", entry("ERROR=%s", e.what()),
                        entry("SRC=%s", src.c_str()),
                        entry("DST=%s", dst.c_str()));
    }
}

std::string Activation::getUpdateService(const std::string& psuInventoryPath)
{
    fs::path imagePath(path());

    // The systemd unit shall be escaped
    std::string args = psuInventoryPath;
    args += "\\x20";
    args += imagePath;
    std::replace(args.begin(), args.end(), '/', '-');

    std::string service = PSU_UPDATE_SERVICE;
    auto p = service.find('@');
    assert(p != std::string::npos);
    service.insert(p + 1, args);
    return service;
}

void ActivationBlocksTransition::enableRebootGuard()
{
    log<level::INFO>("PSU image activating - BMC reboots are disabled.");

    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append("reboot-guard-enable.service", "replace");
    bus.call_noreply_noerror(method);
}

void ActivationBlocksTransition::disableRebootGuard()
{
    log<level::INFO>("PSU activation has ended - BMC reboots are re-enabled.");

    auto method = bus.new_method_call(SYSTEMD_BUSNAME, SYSTEMD_PATH,
                                      SYSTEMD_INTERFACE, "StartUnit");
    method.append("reboot-guard-disable.service", "replace");
    bus.call_noreply_noerror(method);
}

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