#include "NVMeVolume.hpp"

#include "dbus-sensor_config.h"

#include "NVMeCacheImpl.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()),
    NvmeVolumeBase(dynamic_cast<sdbusplus::bus_t&>(*conn),
                   subsys->volumePath(ns.namespaceId).c_str()),
    path(subsys->volumePath(ns.namespaceId)), objServer(objServer), conn(conn),
    subsys(subsys)
{
    namespaceId(ns.namespaceId, false);
    size(ns.size, false);
    blockSize(ns.blockSize, false);
    lbaFormat(ns.lbaFormat, false);
    metadataAtEnd(ns.metadataAtEnd, false);

    // 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 (metricStoreFeature == MetricStoreFeature::Disabled)
    {
        metricStore.emplace(conn->get_io_context(), conn, path);
        return;
    }

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

    using IdentifyMetric =
        IdentifyMetric<NVME_IDENTIFY_CNS_NS, SchedulerClockType>;

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

    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();

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

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();
    NvmeVolumeBase::emit_removed();
    VolumeBase::emit_removed();
    objServer.remove_interface(deleteInterface);
}

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");
}
