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

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 (metricStoreFeature == MetricStoreFeature::Disabled)
    {
        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);
}
