#include "NVMePlugin.hpp"

#include "dbus-sensor_config.h"

#include "NVMeIntf.hpp"
#include "NVMeMetricStore.hpp"
#include "NVMeSubsys.hpp"
#include "Utils.hpp"

#include <phosphor-logging/lg2.hpp>

// map from plugin path (subsystem path) to getMetric function
std::unordered_map<std::string,
                   std::function<std::vector<std::shared_ptr<MetricBase<>>>(
                       const std::string& path)>>
    pluginMetricFunctions;

std::shared_ptr<NVMeControllerPlugin>
    NVMePlugin::createControllerPlugin(const NVMeController& controller,
                                       const SensorData& config)
{
    // searching for the target controller in NVMe subsystem
    auto res = subsystem->controllers.find(controller.getCntrlId());
    if (res == subsystem->controllers.end() ||
        &controller != res->second.first.get())
    {
        lg2::error(
            "Failed to create controller plugin: cannot find the controller");
        res->second.second.reset();
        return {};
    }

    // insert the plugin
    res->second.second = makeController(res->second.first, config);
    return res->second.second;
}

NVMePlugin::NVMePlugin(std::shared_ptr<NVMeSubsystem> subsys,
                       const SensorData& /*config*/) :
    subsystem(std::move(subsys))
{
    // register the path to metric function table.
    auto [_, res] = pluginMetricFunctions.try_emplace(
        getPath(), std::bind_front(&NVMePlugin::getMetric, this));
    assert(res && "found duplicate plugin path for metric function");
}

NVMePlugin::~NVMePlugin()
{
    // remove the metric function
    pluginMetricFunctions.erase(getPath());
}

bool NVMeControllerPlugin::isLogPageSupported(uint8_t lid) const
{
    return nvmeController->isLogPageSupported(lid);
}

const std::string& NVMePlugin::getPath() const
{
    return subsystem->path;
}

const std::string& NVMePlugin::getName() const
{
    return subsystem->name;
}

boost::asio::io_context& NVMePlugin::getIOContext()
{
    return subsystem->io;
}

sdbusplus::asio::object_server& NVMePlugin::getDbusServer()
{
    return subsystem->objServer;
}

std::shared_ptr<sdbusplus::asio::connection> NVMePlugin::getDbusConnection()
{
    return subsystem->conn;
}

const std::map<uint16_t, std::pair<std::shared_ptr<NVMeController>,
                                   std::shared_ptr<NVMeControllerPlugin>>>&
    NVMePlugin::getControllers()
{
    return subsystem->controllers;
}

const std::string& NVMeControllerPlugin::getPath() const
{
    return nvmeController->path;
}

sdbusplus::asio::object_server& NVMeControllerPlugin::getDbusServer()
{
    return nvmeController->objServer;
}

std::shared_ptr<sdbusplus::asio::connection>
    NVMeControllerPlugin::getDbusConnection()
{
    return nvmeController->conn;
}

boost::asio::io_context& NVMeControllerPlugin::getIOContext()
{
    return nvmeController->io;
}

bool NVMeControllerPlugin::isPrimary() const
{
    return nvmeController->isPrimary;
}

void NVMeControllerPlugin::adminXfer(
    const nvme_mi_admin_req_hdr& adminReq, std::span<uint8_t> data,
    unsigned int timeoutMs,
    std::function<void(const std::error_code& ec,
                       const nvme_mi_admin_resp_hdr& adminResp,
                       std::span<uint8_t> respData)>&& cb)
{
    nvmeController->nvmeIntf->adminXfer(nvmeController->nvmeCtrl, adminReq,
                                        data, timeoutMs, std::move(cb));
}

uint16_t NVMeControllerPlugin::getCntrlId() const
{
    return nvmeController->getCntrlId();
}

std::vector<std::shared_ptr<MetricBase<>>>
    MetricStore::getVendorMatrics(const std::string& path)
{
    // if metric store feature is disabled then no vendor metrics should be
    // loaded
    if (!isMetricStoreEnabled())
    {
        return {};
    }

    auto itr = std::find_if(
        pluginMetricFunctions.begin(), pluginMetricFunctions.end(),
        [&path](const std::pair<
                std::string,
                std::function<std::vector<std::shared_ptr<MetricBase<>>>(
                    const std::string& path)>>& pair) {
        // check if the given path is subdir of the subsystem path
        const std::string& parent = pair.first;
        if (parent.empty() || path.empty())
        {
            return false;
        }
        if (parent.size() > path.size())
        {
            return false;
        }
        if (!path.starts_with(parent))
        {
            return false;
        }
        if (parent.back() != '/' && path.size() > parent.size() &&
            path.at(parent.size()) != '/')
        {
            return false;
        }

        return true;
    });
    if (itr == pluginMetricFunctions.end())
    {
        return {};
    }
    if (!itr->second)
    {
        return {};
    }
    return itr->second(path);
}
