#include "NVMeVolume.hpp"

#include "dbus-sensor_config.h"

#include "NVMeCacheImpl.hpp"
#include "Utils.hpp"

using SchedulerClockType = std::chrono::steady_clock;

NVMeVolume::NVMeVolume(sdbusplus::asio::object_server& objServer,
                       const std::shared_ptr<sdbusplus::asio::connection>& conn,
                       const std::shared_ptr<NVMeSubsystem>& subsys,
                       const NVMeNSIdentify& ns) :
    VolumeBase(dynamic_cast<sdbusplus::bus_t&>(*conn),
               subsys->volumePath(ns.namespaceId).c_str()),
    path(subsys->volumePath(ns.namespaceId)), objServer(objServer), conn(conn),
    subsys(subsys), nsIdentify(ns)
{
    size(ns.size, false);
    blockSize(ns.blockSize, false);

    nvmeVolumeInterface =
        objServer.add_interface(path, "xyz.openbmc_project.Nvme.Volume");
    nvmeVolumeInterface->register_property("NamespaceId", ns.namespaceId);
    nvmeVolumeInterface->register_property("LBAFormat",
                                           static_cast<size_t>(ns.lbaFormat));
    nvmeVolumeInterface->register_property("MetadataAtEnd", ns.metadataAtEnd);

    // see init() for other initialisation
}

void NVMeVolume::initializeMetricStore()
{
    // if metric store feature is disabled then create empty metric store
    // the dbus interface will be there but with no metrics
    if (!isMetricStoreEnabled())
    {
        metricStore.emplace(conn->get_io_context(), conn, path);
        return;
    }

    auto scheduler = Scheduler<SchedulerClockType>::getScheduler(path);

    using IdentifyMetric =
        IdentifyMetric<NVME_IDENTIFY_CNS_NS, SchedulerClockType>;

    auto identify = std::make_shared<IdentifyMetric>(
        this->shared_from_this(), scheduler,
        // Identify info is persist throughout the namespace
        // lifecycle i.e. from start() to stop()
        IdentifyMetric::ClockType::duration::max());

    metricStore.emplace(conn->get_io_context(), conn, path,
                        std::move(identify));
}

void NVMeVolume::init()
{
    deleteInterface =
        objServer.add_interface(path, "xyz.openbmc_project.Object.Delete");
    deleteInterface->register_method(
        "Delete", [weak{weak_from_this()}](boost::asio::yield_context yield) {
        auto self = weak.lock();
        if (!self)
        {
            throw std::runtime_error("volume delete called twice?");
        }
        auto subsys = self->subsys.lock();
        if (!subsys)
        {
            throw std::runtime_error("nvmesensor is shutting down");
        }
        subsys->deleteVolume(std::move(yield), self);
    });
    deleteInterface->initialize();

    nvmeVolumeInterface->register_method(
        "Format", [weak{weak_from_this()}](
                      boost::asio::yield_context yield, uint8_t lbaFormat,
                      sdbusplus::xyz::openbmc_project::NVMe::server::Format::
                          SecureEraseSetting secureEraseSetting,
                      sdbusplus::xyz::openbmc_project::NVMe::server::Format::
                          DataProtectionType dataProtectionType) {
        auto self = weak.lock();
        if (!self)
        {
            throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
        }
        self->format(std::move(yield), lbaFormat, secureEraseSetting,
                     dataProtectionType);
    });
    nvmeVolumeInterface->initialize();

    VolumeBase::emit_added();
    initializeMetricStore();
    initializeFeatureStore();
}

std::shared_ptr<NVMeVolume>
    NVMeVolume::create(sdbusplus::asio::object_server& objServer,
                       const std::shared_ptr<sdbusplus::asio::connection>& conn,
                       const std::shared_ptr<NVMeSubsystem>& subsys,
                       const NVMeNSIdentify& ns)
{
    auto self = std::shared_ptr<NVMeVolume>(
        new NVMeVolume(objServer, conn, subsys, ns));
    self->init();
    return self;
}

NVMeVolume::~NVMeVolume()
{
    metricStore.reset();
    VolumeBase::emit_removed();
    objServer.remove_interface(deleteInterface);
    objServer.remove_interface(nvmeVolumeInterface);
}

void NVMeVolume::erase(VolumeBase::EraseMethod eraseType)
{
    (void)eraseType;
    // TODO: will need dbus async method handling.
    throw std::runtime_error("volume erase not yet implemented");
}

// Additional methods on Volume that are not relevant.

void NVMeVolume::formatLuks([[maybe_unused]] std::vector<uint8_t> password,
                            [[maybe_unused]] VolumeBase::FilesystemType type)
{
    throw std::runtime_error("Method Not Supported");
}

void NVMeVolume::lock()
{
    throw std::runtime_error("Method Not Supported");
}

void NVMeVolume::unlock([[maybe_unused]] std::vector<uint8_t> password)
{
    throw std::runtime_error("Method Not Supported");
}

void NVMeVolume::changePassword(
    [[maybe_unused]] std::vector<uint8_t> oldPassword,
    [[maybe_unused]] std::vector<uint8_t> newPassword)
{
    throw std::runtime_error("Method Not Supported");
}

void NVMeVolume::initializeFeatureStore()
{
    if (featureStore)
    {
        return;
    }

    auto subsysPtr = subsys.lock();
    if (!subsysPtr)
    {
        return;
    }

    std::shared_ptr<NVMeControllerEnabled> ctrl;
    try
    {
        ctrl = subsysPtr->getPrimaryController();
    }
    catch (const std::exception& e)
    {
        lg2::error(
            "[{PATH}]Failed to get primary controller for feature store: {ERROR}",
            "PATH", path, "ERROR", e.what());
        return;
    }

    if (!ctrl)
    {
        return;
    }

    this->featureStore = std::make_shared<FeatureStore>(
        conn->get_io_context(), objServer, conn, path, ctrl->getNvmeIntf(),
        ctrl->getMiCtrl(), namespaceId(), FeatureScope::Namespace);

    this->featureStore->init([selfWeak{weak_from_this()},
                              path = this->path](const std::error_code& ec) {
        if (ec)
        {
            if (ec == std::errc::no_such_device ||
                ec == std::errc::not_supported)
            {
                lg2::info(
                    "[{PATH}]Feature store not supported for volume: {ERROR}",
                    "PATH", path, "ERROR", ec.message());
            }
            else
            {
                lg2::error(
                    "[{PATH}]Failed to initialize feature store for volume: {ERROR}",
                    "PATH", path, "ERROR", ec.message());
            }
            auto self = selfWeak.lock();
            if (self)
            {
                self->featureStore.reset();
            }
        }
    });
}

void NVMeVolume::format(
    boost::asio::yield_context yield, uint8_t lbaFormat,
    sdbusplus::xyz::openbmc_project::NVMe::server::Format::SecureEraseSetting
        secureEraseSetting,
    sdbusplus::xyz::openbmc_project::NVMe::server::Format::DataProtectionType
        dataProtectionType)
{
    if (auto s = subsys.lock())
    {
        s->formatNamespace(std::move(yield), lbaFormat, secureEraseSetting,
                           dataProtectionType, nsIdentify.namespaceId);
        return;
    }
    throw sdbusplus::xyz::openbmc_project::Common::Error::Unavailable();
}

void NVMeVolume::updateNSIdentify(const NVMeNSIdentify& ns)
{
    nsIdentify = ns;
    size(ns.size);
    blockSize(ns.blockSize);
    if (nvmeVolumeInterface)
    {
        nvmeVolumeInterface->set_property("NamespaceId", ns.namespaceId);
        nvmeVolumeInterface->set_property("LBAFormat",
                                          static_cast<size_t>(ns.lbaFormat));
        nvmeVolumeInterface->set_property("MetadataAtEnd", ns.metadataAtEnd);
    }
}
