#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("");
        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("drop a duplicated metric", "PATH", objectPath,
                                 "METRIC", emplaceItr->first);
                }
            }
            return temp;
        }(begin, end)),
        validFlag(std::make_shared<bool>())
    {
        insertVUMetrics();
        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;

    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("drop a duplicated vendor 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("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;
};
