/*
// 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 <NVMeBasicContext.hpp>
#include <NVMeContext.hpp>
#include <NVMeMCTPContext.hpp>
#include <NVMeSensor.hpp>
#include <boost/asio/deadline_timer.hpp>

#include <regex>

static constexpr const char* sensorType =
    "xyz.openbmc_project.Configuration.NVME1000";

static NVMEMap nvmeDeviceMap;

static constexpr bool debug = false;

NVMEMap& getNVMEMap()
{
    return nvmeDeviceMap;
}

static void handleSensorConfigurations(
    boost::asio::io_service& io, sdbusplus::asio::object_server& objectServer,
    std::shared_ptr<sdbusplus::asio::connection>& dbusConnection,
    const ManagedObjectType& sensorConfigurations)
{
    // todo: it'd be better to only update the ones we care about
    for (const auto& [_, nvmeContextPtr] : nvmeDeviceMap)
    {
        if (nvmeContextPtr)
        {
            nvmeContextPtr->close();
        }
    }
    nvmeDeviceMap.clear();

    // iterate through all found configurations
    for (const std::pair<sdbusplus::message::object_path, SensorData>& sensor :
         sensorConfigurations)
    {
        const SensorData& sensorData = sensor.second;
        const std::string& interfacePath = sensor.first.str;
        const std::pair<std::string, boost::container::flat_map<
                                         std::string, BasicVariantType>>*
            baseConfiguration = nullptr;

        // find base configuration
        auto sensorBase = sensor.second.find(sensorType);
        if (sensorBase != sensor.second.end())
        {
            baseConfiguration = &(*sensorBase);
        }

        if (baseConfiguration == nullptr)
        {
            continue;
        }
        auto findBus = baseConfiguration->second.find("Bus");
        if (findBus == baseConfiguration->second.end())
        {
            continue;
        }

        int busNumber = std::visit(VariantToIntVisitor(), findBus->second);

        auto findSensorName = baseConfiguration->second.find("Name");
        if (findSensorName == baseConfiguration->second.end())
        {
            std::cerr << "could not determine configuration name for "
                      << interfacePath << "\n";
            continue;
        }
        std::string sensorName = std::get<std::string>(findSensorName->second);

        std::vector<thresholds::Threshold> sensorThresholds;

        if (!parseThresholdsFromConfig(sensorData, sensorThresholds))
        {
            std::cerr << "error populating thresholds for " << sensorName
                      << "\n";
        }

        int rootBus = busNumber;

        std::string muxPath = "/sys/bus/i2c/devices/i2c-" +
                              std::to_string(busNumber) + "/mux_device";

        if (std::filesystem::is_symlink(muxPath))
        {
            std::string rootName =
                std::filesystem::read_symlink(muxPath).filename();
            size_t dash = rootName.find('-');
            if (dash == std::string::npos)
            {
                std::cerr << "Error finding root bus for " << rootName << "\n";
                continue;
            }
            rootBus = std::stoi(rootName.substr(0, dash));
        }

        std::shared_ptr<NVMeContext> context;
        auto findRoot = nvmeDeviceMap.find(rootBus);
        if (findRoot != nvmeDeviceMap.end())
        {
            context = findRoot->second;
        }
        else
        {
#if HAVE_NVME_MI_MCTP
            context = std::make_shared<NVMeMCTPContext>(io, rootBus);
#else
            context = std::make_shared<NVMeBasicContext>(io, rootBus);
#endif
            nvmeDeviceMap[rootBus] = context;
        }

        std::shared_ptr<NVMeSensor> sensorPtr = std::make_shared<NVMeSensor>(
            objectServer, io, dbusConnection, sensorName,
            std::move(sensorThresholds), interfacePath, busNumber);

        context->addSensor(sensorPtr);
    }
    for (const auto& [_, context] : nvmeDeviceMap)
    {
        context->pollNVMeDevices();
    }
}

void createSensors(boost::asio::io_service& io,
                   sdbusplus::asio::object_server& objectServer,
                   std::shared_ptr<sdbusplus::asio::connection>& dbusConnection)
{

    auto getter = std::make_shared<GetSensorConfiguration>(
        dbusConnection,
        std::move([&io, &objectServer, &dbusConnection](
                      const ManagedObjectType& sensorConfigurations) {
            handleSensorConfigurations(io, objectServer, dbusConnection,
                                       sensorConfigurations);
        }));
    getter->getConfiguration(std::vector<std::string>{sensorType});
}

int main()
{
    boost::asio::io_service io;
    auto systemBus = std::make_shared<sdbusplus::asio::connection>(io);
    systemBus->request_name("xyz.openbmc_project.NVMeSensor");
    sdbusplus::asio::object_server objectServer(systemBus);
#if HAVE_NVME_MI_MCTP
    nvmeMCTP::init();
#endif

    io.post([&]() { createSensors(io, objectServer, systemBus); });

    boost::asio::deadline_timer filterTimer(io);
    std::function<void(sdbusplus::message::message&)> eventHandler =
        [&filterTimer, &io, &objectServer,
         &systemBus](sdbusplus::message::message&) {
            // this implicitly cancels the timer
            filterTimer.expires_from_now(boost::posix_time::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)
                {
                    std::cerr << "Error: " << ec.message() << "\n";
                    return;
                }

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

    sdbusplus::bus::match::match configMatch(
        static_cast<sdbusplus::bus::bus&>(*systemBus),
        "type='signal',member='PropertiesChanged',path_namespace='" +
            std::string(inventoryPath) + "',arg0namespace='" +
            std::string(sensorType) + "'",
        eventHandler);

    setupManufacturingModeMatch(*systemBus);
    io.run();
}
