#pragma once

/**
 * This file defines the MetricStore class, which is the DBus inplemention to
 * interact with a collection of NVMe Metrics Cache for a Storage
 * object(e.g. NVMe Contoller)
 */

#include "NVMeCache.hpp"

#include <boost/asio.hpp>
#include <boost/asio/write.hpp>
#include <boost/endian.hpp>
#include <sdbusplus/asio/connection.hpp>
#include <sdbusplus/asio/object_server.hpp>
#include <sdbusplus/sdbus.hpp>
#include <sdbusplus/server.hpp>
#include <xyz/openbmc_project/NVMe/MetricStore/server.hpp>

#include <functional>
#include <memory>
#include <string>
#include <tuple>
#include <unordered_map>

constexpr bool debug = false;

struct MetricHeader
{
    boost::endian::little_uint32_t lens;    // Header length
    boost::endian::little_uint16_t version; // Header version
    uint8_t dataFormat; // the data format. 0x00 = Raw NVMe format
    uint8_t reserved;
    boost::endian::little_uint64_t
        startTime;  // time stamp when the Metric started the retrival from the
                    // device
    boost::endian::little_uint64_t
        finishTime; // time stamp when the Metric finished the retrival from
                    // the device
};

class MetricStore :
    public sdbusplus::xyz::openbmc_project::NVMe::server::MetricStore
{
    friend class TestNVMeRefresh;

  public:
    template <class... Args>
        requires(std::is_base_of_v<MetricBase<std::chrono::steady_clock>,
                                   Args> &&
                 ...)
    MetricStore(boost::asio::io_context& io,
                const std::shared_ptr<sdbusplus::asio::connection>& conn,
                const std::string& objectPath,
                std::shared_ptr<Args>&&... metrics) :
        sdbusplus::xyz::openbmc_project::NVMe::server::MetricStore(
            dynamic_cast<sdbusplus::bus_t&>(*conn), objectPath.c_str()),
        path(objectPath), io(io),
        metricStore{{std::string{metrics ? metrics->getIdentifier() : ""},
                     std::move(metrics)}...},
        validFlag(std::make_shared<bool>())
    {
        metricStore.erase("");
        insertVUMetrics();
        emit_added();
    }

    template <class Itr>
        requires(std::is_base_of_v<
                    MetricBase<std::chrono::steady_clock>,
                    typename std::pointer_traits<
                        typename std::iter_value_t<Itr>>::element_type>)
    MetricStore(boost::asio::io_context& io,
                const std::shared_ptr<sdbusplus::asio::connection>& conn,
                const std::string& objectPath, const Itr& begin,
                const Itr& end) :
        sdbusplus::xyz::openbmc_project::NVMe::server::MetricStore(
            dynamic_cast<sdbusplus::bus_t&>(*conn), objectPath.c_str()),
        path(objectPath), io(io),
        metricStore([&objectPath](const Itr& begin, const Itr& end) {
            std::unordered_map<std::string, std::shared_ptr<MetricBase<>>> temp;
            for (auto itr = begin; itr != end; ++itr)
            {
                auto& metric = *itr;
                if (!metric || metric->getIdentifier().empty())
                {
                    continue;
                }
                auto [emplaceItr, res] = temp.try_emplace(
                    std::string{metric->getIdentifier()}, metric);
                if (!res)
                {
                    lg2::warning("[{PATH}]drop a duplicated metric: {METRIC}",
                                 "PATH", objectPath, "METRIC",
                                 emplaceItr->first);
                }
            }
            return temp;
        }(begin, end)),
        validFlag(std::make_shared<bool>())
    {
        insertVUMetrics();
        emit_added();
    }
    ~MetricStore() override
    {
        emit_removed();
    }

  private:
    /**
     * @brief Refresh the metrics
     *
     * @param[in] name: metric name
     *
     * @return sdbusplus::message::unix_fd: Returns the read end of the pipe
     */
    sdbusplus::message::unix_fd refreshMetric(std::string name) override;
    static std::vector<std::shared_ptr<MetricBase<>>>
        getVendorMatrics(const std::string& path);
    /**
     * @brief Writes to file descriptor after getting results from the
     * registered callback function
     *
     * @param[in] data: Vector of raw bytes (header + actual data) to be written
     * to file descriptor
     *
     * @return sdbusplus::message::unix_fd: Returns the read end of the pipe
     */
    sdbusplus::message::unix_fd writeToFd(std::span<const uint8_t> header,
                                          std::span<const uint8_t> data);

    /**
     * @brief Gets Metric using a unique metric name. Metric must be registered
     * with that unique name
     *
     * @param[in] name: Registered metric name
     *
     * @return file descriptor pointing to the data
     */
    sdbusplus::message::unix_fd getMetric(std::string name) override; // NOLINT

    /**
     * @brief A helper function to signal MetricUpdated
     *
     * @param[in] name: metric name
     * @param[in] metric: metric instance. null instance will trigger invalid
     * signal
     */
    void signalHelper(
        std::string_view name,
        const std::shared_ptr<MetricBase<std::chrono::steady_clock>>&
            metric) noexcept;

    inline void insertVUMetrics()
    {
        auto vuMetrics = getVendorMatrics(path);
        for (auto& metric : vuMetrics)
        {
            if (!metric)
            {
                continue;
            }
            auto [itr, res] = metricStore.try_emplace(
                std::string{metric->getIdentifier()}, std::move(metric));
            if (!res)
            {
                lg2::warning(
                    "[{PATH}]drop a duplicated vendor metric: {METRIC}", "PATH",
                    path, "METRIC", itr->first);
            }
        }

        std::vector<std::string> idCollection;
        decltype(validFlag)::weak_type weakFlag = validFlag;
        for (auto& [identifier, metric] : metricStore)
        {
            idCollection.push_back(identifier);
            std::weak_ptr<MetricBase<std::chrono::steady_clock>> weakMetric =
                metric;
            metric->registerCompleteCB([this, weakFlag, identifier, weakMetric,
                                        path{path}](std::error_code ec) {
                // use validFlag to protect this call
                if (weakFlag.expired())
                {
                    lg2::info(
                        "[{PATH}]MetricStore interface expired, update signal "
                        "skipped.",
                        "PATH", path);
                    return;
                }
                auto metric = weakMetric.lock();
                if (ec || !metric)
                {
                    // broadcast invalid metric signal
                    this->signalHelper(identifier, {});
                }
                this->signalHelper(identifier, metric);
            });
            metric->refresh({});
        }
        metricCollection(std::move(idCollection), true);
    }

    std::string path;
    boost::asio::io_context& io;
    std::unordered_map<std::string, std::shared_ptr<MetricBase<>>> metricStore;
    // A flag to check the validation of this ptr when this is captured by async
    // function. No other oject should seize the strong ptr of the flag other
    // than this instance.
    std::shared_ptr<bool> validFlag;
};
