#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
{
  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("");
        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("drop a duplicated vendor metic", "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{objectPath}](std::error_code ec) {
                // use validFlag to protect this call
                if (weakFlag.expired())
                {
                    lg2::info("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);
        emit_added();
    }
    ~MetricStore() override
    {
        emit_removed();
    }

  private:
    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;

    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;
};
