/*
// Copyright (c) 2019 Intel Corporation
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
*/

#include "MctpEndpoint.hpp"
#include "MctpReactorDevice.hpp"
#include "NVMeBasic.hpp"
#include "NVMeDevice.hpp"
#include "NVMeIntf.hpp"
#include "NVMeMi.hpp"
#include "NVMePlugin.hpp"
#include "NVMeSubsys.hpp"
#include "Utils.hpp"

#include <dlfcn.h>

#include <boost/algorithm/string.hpp>
#include <boost/asio/steady_timer.hpp>
#include <phosphor-logging/lg2.hpp>

#include <filesystem>
#include <fstream>
#include <optional>
#include <regex>
#include <system_error>
#include <unordered_set>

// a map with key value of {path, NVMeSubsystem}
using NVMEMap = std::map<std::string, std::shared_ptr<NVMeDevice>>;
static NVMEMap nvmeDevices;

// A map from root bus number to the Worker
// This map means to reuse the same worker for all NVMe EP under the same
// I2C root bus. There is no real physical concurrency among the i2c/mctp
// devices on the same bus. Though mctp kernel drive can schedule and
// sequencialize the transactions but assigning individual worker thread to
// each EP makes no sense.
static std::map<int, std::weak_ptr<NVMeMiWorker>> i2cWorkerMap{};

std::unordered_map<std::string, void*> pluginLibMap = {};

static std::unordered_set<int> bannedBuses;

static void initBannedI2cBus()
{
    const std::string script = "/usr/bin/init-banned-i2c-bus.sh";
    const std::string confPath = "/var/run/nvmed/banned-i2c-bus.conf";
    if (!std::filesystem::exists(script))
    {
        lg2::error("Script {SCRIPT} doesn't exist", "SCRIPT", script);
        return;
    }

    lg2::info("Begin to execute {SCRIPT}", "SCRIPT", script);
    // TODO: (b/376270522) cert-env33-c error: calling 'system' uses a command
    // processor
    int rc = std::system(script.c_str()); // NOLINT(cert-env33-c)
    lg2::info("Shell script rc = {RC}", "RC", rc);

    if (!std::filesystem::exists(confPath))
    {
        lg2::warning("Warning: {CONF_PATH} doesn't exist.", "CONF_PATH",
                     confPath);
        // Be optimistic，assume no bus is banned
        return;
    }
    std::ifstream file;
    file.open(confPath);
    if (!file.is_open())
    {
        lg2::error("Error: cannot open {CONF_PATH}", "CONF_PATH", confPath);
        // Be optimistic，assume no bus is banned
        return;
    }

    bannedBuses.clear();
    int i2cBus{0};
    while (file >> i2cBus)
    {
        lg2::info("Banned i2c bus: {BUS}", "BUS", i2cBus);
        bannedBuses.insert(i2cBus);
    }
    file.close();
}

static std::optional<int>
    extractBusNumber(const std::string& path,
                     const SensorBaseConfigMap& properties)
{
    auto findBus = properties.find("Bus");
    if (findBus == properties.end())
    {
        lg2::error("could not determine bus number for '{PATH}'", "PATH", path);
        return std::nullopt;
    }

    return std::visit(VariantToIntVisitor(), findBus->second);
}

static std::optional<int> extractAddress(const std::string& path,
                                         const SensorBaseConfigMap& properties)
{
    auto findAddr = properties.find("Address");
    if (findAddr == properties.end())
    {
        lg2::error("could not determine address for '{PATH}'", "PATH", path);
        return std::nullopt;
    }

    return std::visit(VariantToIntVisitor(), findAddr->second);
}

static std::optional<std::string>
    extractName(const std::string& path, const SensorBaseConfigMap& properties)
{
    auto findName = properties.find("Name");
    if (findName == properties.end())
    {
        lg2::error("could not determine configuration name for '{PATH}'",
                   "PATH", path);
        return std::nullopt;
    }

    return std::get<std::string>(findName->second);
}

static std::optional<std::string>
    extractProtocol(const std::string& path,
                    const SensorBaseConfigMap& properties)
{
    auto findProtocol = properties.find("Protocol");
    if (findProtocol == properties.end())
    {
        lg2::error("could not determine nvme protocol for '{PATH}'", "PATH",
                   path);
        return std::nullopt;
    }
    return std::get<std::string>(findProtocol->second);
}

static std::optional<std::string>
    extractMctpReactorConfigPath(const SensorBaseConfigMap& properties)
{
    auto findMctpReactorConfigPath = properties.find("MctpReactorConfigPath");
    if (findMctpReactorConfigPath == properties.end())
    {
        return std::nullopt;
    }
    return std::get<std::string>(findMctpReactorConfigPath->second);
}

static bool hasLockdownFeature(const std::string& path,
                               const SensorBaseConfigMap& properties)
{
    auto it = properties.find("SupportedFeatures");
    if (it == properties.end())
    {
        return false;
    }

    const auto& value = it->second;

    if (std::holds_alternative<std::vector<std::string>>(value))
    {
        const auto& features =
            std::get<std::vector<std::string>>(value); // Safe now
        for (const auto& feature : features)
        {
            if (feature == "Lockdown")
            {
                return true;
            }
        }
    }
    else
    {
        lg2::warning(
            "'{PATH}': 'SupportedFeatures' is not an array of strings.", "PATH",
            path);
    }
    return false;
}

static void handleConfigurations(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    const ManagedObjectType& nvmeConfigurations)
{
    // Initialize banned i2c bus info on every configuration change
    initBannedI2cBus();

    for (const auto& [nvmeObjectPath, configData] : nvmeConfigurations)
    {
        // find base configuration
        auto sensorBase =
            configData.find(configInterfaceName(nvme::sensorType));
        if (sensorBase == configData.end())
        {
            continue;
        }

        const SensorBaseConfigMap& sensorConfig = sensorBase->second;
        std::optional<int> busNumber = extractBusNumber(nvmeObjectPath,
                                                        sensorConfig);
        std::optional<int> address = extractAddress(nvmeObjectPath,
                                                    sensorConfig);
        std::optional<std::string> sensorName = extractName(nvmeObjectPath,
                                                            sensorConfig);
        std::optional<std::string> nvmeProtocol =
            extractProtocol(nvmeObjectPath, sensorConfig);
        std::optional<std::string> mctpReactorConfigPath =
            extractMctpReactorConfigPath(sensorConfig);

        bool enableFeatureLockdown = hasLockdownFeature(nvmeObjectPath,
                                                        sensorConfig);

        if (!sensorName)
        {
            continue;
        }

        const bool isMctpReactorDevice = mctpReactorConfigPath.has_value();

        // Some NVMe devices are accessible over I2C because they're connected
        // over SMBus directly to the BMC. In other cases, they might be
        // connected to the BMC through a bridge (such as
        // MCTP USB <-> I2C bridge).
        const bool isI2cAccessible = busNumber.has_value();

        // If a device is not an mctpreactor device, it must be accessible over
        // I2C directly.
        if (!isMctpReactorDevice && !isI2cAccessible)
        {
            lg2::info("Found an mctpd device that isn't I2C accessible,"
                      "but it must be: {PATH}",
                      "PATH", nvmeObjectPath.str);
            continue;
        }

        if (busNumber && bannedBuses.contains(*busNumber))
        {
            lg2::info("Skip banned i2c bus: {BUS}", "BUS", *busNumber);
            continue;
        }

        // the default protocol is mi_basic
        if (!nvmeProtocol)
        {
            nvmeProtocol.emplace("mi_basic");
        }

        // Support for non-I2C-accessible devices doesn't exist for mi_basic
        // protocol because we don't need it for now.
        if (*nvmeProtocol == "mi_basic" && !isI2cAccessible)
        {
            lg2::info("Skipping an mi_basic device that's not accessible "
                      "over i2c bus.");
            continue;
        }

        if (*nvmeProtocol == "mi_basic")
        {
            // defualt i2c basic port is 0x6a
            if (!address)
            {
                address.emplace(0x6a);
            }
            try
            {
                NVMeIntf nvmeIntf = NVMeIntf::create<NVMeBasic>(io, *busNumber,
                                                                *address);

                auto nvmeSubsys = NVMeSubsystem::create(
                    io, objectServer, dbusConnection, nvmeObjectPath,
                    *sensorName, configData, nvmeIntf, enableFeatureLockdown);
                auto nvmeDev = NVMeDevice::create(std::move(nvmeIntf),
                                                  nvmeSubsys);
                auto [entry, added] = nvmeDevices.try_emplace(nvmeObjectPath,
                                                              nvmeDev);
                if (added)
                {
                    entry->second->start();
                }
            }
            catch (std::exception& ex)
            {
                lg2::error(
                    "Failed to add nvme basic interface for '{PATH}': {ERROR}",
                    "PATH", nvmeObjectPath.str, "ERROR", ex.what());
            }
        }
        else if (*nvmeProtocol == "mi_i2c")
        {
            // defualt i2c nvme-mi port is 0x1d
            if (!address)
            {
                address.emplace(0x1d);
            }
            PowerState powerState = getPowerState(sensorConfig);

            std::shared_ptr<NVMeMiWorker> worker;
            if (singleWorkerFeature && isI2cAccessible)
            {
                auto root = deriveRootBus(*busNumber);

                if (!root || *root < 0)
                {
                    throw std::runtime_error("invalid root bus number");
                }
                auto res = i2cWorkerMap.find(*root);

                if (res == i2cWorkerMap.end() || res->second.expired())
                {
                    worker = NVMeMiWorker::create(io);
                    i2cWorkerMap[*root] = worker;
                }
                else
                {
                    worker = res->second.lock();
                }
            }
            else
            {
                worker = NVMeMiWorker::create(io);
            }

            try
            {
                // Note that in this codepath, despite using "mi_i2c" protocol,
                // we can be talking to NVMe devices not accessible through I2C
                // directly.
                std::shared_ptr<MctpDevice> mctpDev;
                if (!isMctpReactorDevice)
                {
                    mctpDev = std::make_shared<SmbusMctpdDevice>(
                        dbusConnection, *busNumber, *address);
                }
                else // isMctpReactorDevice
                {
                    mctpDev = std::make_shared<MctpReactorDevice>(
                        dbusConnection, *mctpReactorConfigPath, busNumber,
                        address);
                }

                NVMeIntf nvmeIntf = NVMeIntf::create<NVMeMi>(
                    io, dbusConnection, mctpDev, worker, powerState);
                auto nvmeSubsys = NVMeSubsystem::create(
                    io, objectServer, dbusConnection, nvmeObjectPath,
                    *sensorName, configData, nvmeIntf, enableFeatureLockdown);

                auto nvmeDev = NVMeDevice::create(
                    io, mctpDev, std::move(nvmeIntf), nvmeSubsys);
                auto [entry, added] = nvmeDevices.try_emplace(nvmeObjectPath,
                                                              nvmeDev);
                if (added)
                {
                    entry->second->start();
                }
            }
            catch (std::exception& ex)
            {
                lg2::error(
                    "Failed to add nvme mi interface for '{PATH}': {ERROR}",
                    "PATH", nvmeObjectPath.str, "ERROR", ex.what());
            }
        }
    }
}

void createNVMeSubsystems(
    boost::asio::io_context& io, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{
    // todo: it'd be better to only update the ones we care about
    for (auto& [_, nvmeDev] : nvmeDevices)
    {
        nvmeDev->stop();
    }
    nvmeDevices.clear();

    static int count = 0;
    static ManagedObjectType configs;
    count += 2;

    auto getter = std::make_shared<GetSensorConfiguration>(
        dbusConnection, [&io, &objectServer, &dbusConnection](
                            const ManagedObjectType& nvmeConfigurations) {
        configs = nvmeConfigurations;
        count--;
        if (count == 0)
        {
            handleConfigurations(io, objectServer, dbusConnection, configs);
        }
        else
        {
            lg2::error("more than one `handleConfigurations` has been "
                       "scheduled, cancel the current one");
        }
    });
    auto timer = std::make_shared<boost::asio::steady_timer>(
        io, std::chrono::seconds(10));
    timer->async_wait([&io, &objectServer, &dbusConnection,
                       timer](const boost::system::error_code& ec) {
        count--;
        if (ec)
        {
            return;
        }
        if (count == 0)
        {
            handleConfigurations(io, objectServer, dbusConnection, configs);
        }
        else
        {
            lg2::error("`handleConfigurations` has not been triggered, "
                       "cancel the timer");
        }
    });

    getter->getConfiguration(std::vector<std::string>{nvme::sensorType});
}

static void interfaceRemoved(sdbusplus::message_t& message, NVMEMap& devices)
{
    if (message.is_method_error())
    {
        lg2::error("interfacesRemoved callback method error");
        return;
    }

    sdbusplus::message::object_path path;
    std::vector<std::string> interfaces;

    message.read(path, interfaces);

    auto interface = std::find(interfaces.begin(), interfaces.end(),
                               configInterfaceName(nvme::sensorType));
    if (interface == interfaces.end())
    {
        return;
    }

    auto device = devices.find(path);
    if (device == devices.end())
    {
        return;
    }

    device->second->stop();
    devices.erase(device);
}

int main(int argc, char** argv)
{
    for (int i = 1; i < argc; ++i)
    {
        std::string_view arg(argv[i]);
        if (arg == "--enable-metrics")
        {
            setMetricStoreEnabled(true);
            lg2::info("Metric store runtime override: enabled via CLI");
        }
        else if (arg == "--disable-metrics")
        {
            setMetricStoreEnabled(false);
            lg2::info("Metric store runtime override: disabled via CLI");
        }
    }

    if (singleWorkerFeature)
    {
        lg2::info("singleWorkerFeature on");
    }

    // Load plugin shared libraries
    try
    {
        for (const auto& entry :
             std::filesystem::directory_iterator(NVMePlugin::libraryPath))
        {
            void* lib = dlopen(entry.path().c_str(), RTLD_NOW);
            if (lib != nullptr)
            {
                pluginLibMap.emplace(entry.path().filename().string(), lib);
            }
            else
            {
                lg2::error("could not load the plugin: {ERROR}", "ERROR",
                           dlerror());
            }
        }
    }
    catch (const std::filesystem::filesystem_error& e)
    {
        lg2::error("failed to open plugin folder: {ERROR}", "ERROR", e.what());
    }

    // TODO: set single thread mode according to input parameters

    boost::asio::io_context io;
    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
    systemBus->request_name("xyz.openbmc_project.NVMe");
    sdbusplus::asio::object_server objectServer(systemBus, true);
    objectServer.add_manager("/xyz/openbmc_project/sensors");
    objectServer.add_manager("/xyz/openbmc_project/inventory");

    boost::asio::post(
        io, [&]() { createNVMeSubsystems(io, objectServer, systemBus); });

    boost::asio::steady_timer filterTimer(io);
    std::function<void(sdbusplus::message_t&)> eventHandler =
        [&filterTimer, &io, &objectServer, &systemBus](sdbusplus::message_t&) {
        // this implicitly cancels the timer
        filterTimer.expires_after(std::chrono::seconds(1));

        filterTimer.async_wait([&](const boost::system::error_code& ec) {
            if (ec == boost::asio::error::operation_aborted)
            {
                return; // we're being canceled
            }

            if (ec)
            {
                lg2::error("Error: {ERROR}", "ERROR", ec.message());
                return;
            }

            createNVMeSubsystems(io, objectServer, systemBus);
        });
    };

    std::vector<std::unique_ptr<sdbusplus::bus::match_t>> matches =
        setupPropertiesChangedMatches(
            *systemBus, std::to_array<const char*>({NVMeSensor::sensorType}),
            eventHandler);

    // Watch for entity-manager to remove configuration interfaces
    // so the corresponding sensors can be removed.
    auto ifaceRemovedMatch = std::make_unique<sdbusplus::bus::match_t>(
        static_cast<sdbusplus::bus_t&>(*systemBus),
        "type='signal',member='InterfacesRemoved',arg0path='" +
            std::string(inventoryPath) + "/'",
        [](sdbusplus::message_t& msg) { interfaceRemoved(msg, nvmeDevices); });

    setupManufacturingModeMatch(*systemBus);

    // The NVMe controller used pipe to transfer raw data. The pipe could be
    // closed by the client. It should not be considered as an error.
    boost::asio::signal_set signals(io, SIGPIPE);
    signals.async_wait(
        [](const boost::system::error_code& error, int signalNumber) {
        lg2::info("signal: {SIGNAL}, {ERROR}", "SIGNAL",
                  strsignal(signalNumber), "ERROR", error.message());
    });
    io.run();

    for (const auto& [_, lib] : pluginLibMap)
    {
        dlclose(lib);
    }
}
