#include "NVMeDrive.hpp"

#include "NVMeError.hpp"
#include "NVMeSubsys.hpp"

#include <phosphor-logging/lg2.hpp>

namespace common_err = sdbusplus::xyz::openbmc_project::Common::Error;

NVMeDrive::NVMeDrive(boost::asio::io_context& io,
                     const std::shared_ptr<sdbusplus::asio::connection>& conn,
                     const std::string& path,
                     std::weak_ptr<NVMeSubsystem> subsys) :
    DriveBase(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str()),
    DriveErase(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str()),
    Asset(dynamic_cast<sdbusplus::bus_t&>(*conn), path.c_str()), path(path),
    sanitizeTimer(io), io(io), subsys(std::move(subsys))
{
    DriveBase::emit_added();
    DriveErase::emit_added();
    Asset::emit_added();
}

NVMeDrive::~NVMeDrive()
{
    sanitizeTimer.cancel();
    Asset::emit_removed();
    DriveErase::emit_removed();
    DriveBase::emit_removed();
}

// DriveErase.Erase method handler
void NVMeDrive::erase(EraseAction action)
{
    std::shared_ptr<NVMeSubsystem> s = subsys.lock();
    if (!s)
    {
        throw std::runtime_error("Sanitize called while shutting down");
    }

    NVMeSanitizeParams params(action);

    if (eraseInProgress())
    {
        // Already running
        if (params == sanitizeParams)
        {
            return;
        }
        // TODO: (b/375054188) Exception handling to be refactored
        // NOLINTNEXTLINE(cert-err09-cpp,cert-err60-cpp,cert-err61-cpp,misc-throw-by-value-catch-by-reference)
        throw *makeLibNVMeError(
            "sanitize already in progress with different parameters",
            std::make_shared<common_err::Unavailable>());
    }
    sanitizeParams = params;

    // Clear properties
    erasePercentage(0.0);
    errorName("");
    errorDescription("");
    // eraseInProgress() should always be set last.
    eraseInProgress(true);

    s->startSanitize(params, [self{shared_from_this()}](const nvme_ex_ptr& ex) {
        if (ex)
        {
            // Update properties with the submission failure
            self->erasePercentage(0.0);
            self->errorName(ex->name());
            self->errorDescription(ex->description());
            self->eraseInProgress(false);
        }
        else
        {
            // start the timer
            self->sanitizePoll();
        }
    });
}

void NVMeDrive::sanitizePoll()
{
    if (sanitizePollPending)
    {
        return;
    }
    sanitizePollPending = true;
    sanitizeTimer.expires_after(std::chrono::seconds(sanitizePollIntervalSecs));
    sanitizeTimer.async_wait(
        [weak{weak_from_this()}](boost::system::error_code ec) {
        if (ec == boost::asio::error::operation_aborted)
        {
            return;
        }

        auto self = weak.lock();
        if (!self)
        {
            return;
        }
        std::shared_ptr<NVMeSubsystem> s = self->subsys.lock();
        if (!s)
        {
            return;
        }

        self->sanitizePollPending = false;

        if (self->eraseInProgress())
        {
            s->sanitizeStatus([self](const nvme_ex_ptr& ex, bool inProgress,
                                     bool failed, bool completed,
                                     uint16_t sstat, uint16_t sprog,
                                     uint32_t scdw10) {
                (void)sstat;
                (void)sprog;
                (void)scdw10;
                if (ex)
                {
                    lg2::error("Error returned reading sanitize log: {ERROR}",
                               "ERROR", ex->what());
                }
                else
                {
                    if (completed)
                    {
                        self->erasePercentage(0.0);
                        self->eraseInProgress(false);
                    }
                    else if (failed)
                    {
                        self->erasePercentage(0.0);
                        self->eraseInProgress(false);
                        self->errorName(
                            common_err::DeviceOperationFailed::errName);
                        self->errorDescription("Sanitize operation failed");
                    }
                    else if (inProgress)
                    {
                        self->erasePercentage(100.0 * sprog / 0x10000);
                    }
                }

                if (self->eraseInProgress())
                {
                    self->sanitizePoll();
                }
            });
        }
    });
}

NVMeSanitizeParams::NVMeSanitizeParams(EraseAction sanact) :
    sanact(sanact), passes(1), pattern(0x0), patternInvert(false)
{}

enum nvme_sanitize_sanact NVMeSanitizeParams::nvmeAction() const
{
    switch (sanact)
    {
        case EraseAction::BlockErase:
            return NVME_SANITIZE_SANACT_START_BLOCK_ERASE;
        case EraseAction::CryptoErase:
            return NVME_SANITIZE_SANACT_START_CRYPTO_ERASE;
        case EraseAction::Overwrite:
            return NVME_SANITIZE_SANACT_START_OVERWRITE;
    }
    throw std::logic_error("unreachable");
}

bool NVMeSanitizeParams::matchesDword10(uint32_t dword10) const
{
    uint32_t ownDword10 = 0;

    // reconstruct the dword10 sent by libnvme
    ownDword10 |= (uint32_t)nvmeAction();
    ownDword10 |= (((uint32_t)patternInvert) << 8);
    ownDword10 |= (((uint32_t)passes & 0xf) << 4);

    return dword10 == ownDword10;
}
