#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 <iostream>
#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)
            {
                std::cerr << std::format(
                    "[{}, {}] drop a duplicated vendor metic\n", path,
                    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())
                {
                    // TODO: log_level = INFO
                    std::cerr << std::format(
                        "[{}]MetricStore interface expired, update signal skipped.\n",
                        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;
};
