#include "NVMeVolume.hpp"

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

    /* create the MetricStore interface */
    auto scheduler = Scheduler<SchedulerClockType>::getScheduler(path);

    // NOLINTBEGIN(performance-unnecessary-value-param)
    auto completeCB =
        [wealSelf{weak_from_this()},
         path{path}](std::string_view name,
                     std::shared_ptr<MetricBase<SchedulerClockType>> metric) {
        auto self = wealSelf.lock();
        if (!self || !self->metricStore)
        {
            // TODO: log_level = INFO
            std::cerr << std::format(
                "[{}]Metrics interface for controller expired, update signal skipped.\n",
                path);
        }
        if (!metric->isCacheValid())
        {
            // broadcast invalid metric signal
            self->metricStore->metricUpdated(std::string{name}, {});
            return;
        }

        auto data = metric->getCache();
        std::vector<uint8_t> headerBuf;
        headerBuf.resize(sizeof(MetricHeader));
        MetricHeader& header =
            // NOLINTNEXTLINE(cppcoreguidelines-pro-type-reinterpret-cast)
            *reinterpret_cast<MetricHeader*>(headerBuf.data());
        header.lens = boost::endian::little_uint32_t(sizeof(header));
        header.version = 0;
        header.dataFormat = 0;
        header.startTime = boost::endian::little_uint64_t(
            std::get<0>(data).time_since_epoch().count());
        header.finishTime = boost::endian::little_uint64_t(
            std::get<1>(data).time_since_epoch().count());
        self->metricStore->metricUpdated(std::string{name}, headerBuf);
    };
    // NOLINTEND(performance-unnecessary-value-param)

    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(),
        std::bind_front(completeCB, IdentifyMetric::identifyIdentifier())));
    // NOLINTEND(modernize-make-shared)

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

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