#pragma once
/**
 * This file contains all cache implementation of types of Metrics
 */

#include "NVMeCache.hpp"
#include "NVMeController.hpp"

/**
 * Metric implementation for LogPage
 */

template <nvme_cmd_get_log_lid LID, class ClockType>
class ControllerLogPageMetric : public MetricBase<ClockType>
{
  public:
    ControllerLogPageMetric(
        std::weak_ptr<NVMeControllerEnabled> controller,
        std::shared_ptr<Scheduler<ClockType>> scheduler,
        ClockType::duration interval,
        std::function<void(std::shared_ptr<MetricBase<ClockType>>)>&&
            completeCB) :
        MetricBase<ClockType>(scheduler, interval),
        controller(std::move(controller)), completeCB(std::move(completeCB))
    {}

    /* interface overrides */
    static constexpr std::string_view logpageIdentifier() noexcept
    {
        if constexpr (LID == NVME_LOG_LID_ERROR)
        {
            return "ErrorInfoMetric";
        }
        else if constexpr (LID == NVME_LOG_LID_SMART)
        {
            return "SMARTMetric";
        }
        else if constexpr (LID == NVME_LOG_LID_FW_SLOT)
        {
            return "FwSlotInfoMetric";
        }
        else if constexpr (LID == NVME_LOG_LID_DEVICE_SELF_TEST)
        {
            return "DeviceSelfTestMetric";
        }
        else if constexpr (LID == NVME_LOG_LID_TELEMETRY_HOST)
        {
            return "HostInitiatedMetric";
        }
        else
        {
            static_assert(false,
                          "LID not supported by ControllerLogPageMetric");
        }

        return {};
    }

    constexpr std::string_view getIdentifier() const noexcept override
    {
        return logpageIdentifier();
    }

    bool isCacheValid() const noexcept override
    {
        return cacheValid;
    }
    std::tuple<std::chrono::time_point<ClockType>,
               std::chrono::time_point<ClockType>, std::span<const uint8_t>>
        getCache() const noexcept override
    {
        std::chrono::time_point<ClockType> start = std::get<0>(cache);
        std::chrono::time_point<ClockType> stop = std::get<1>(cache);
        auto& data = std::get<2>(cache);
        return {start, stop,
                std::span<const uint8_t>(data.begin(), data.end())};
    }

    /* internal overrides */
  private:
    // read data from device and update the
    // implemetation should extend this virtual function and do the real
    // data fetch from device.
    void readDevice(std::function<void(std::error_code ec, size_t size,
                                       bool complete)>&& cb) noexcept override
    {
        auto startTime = ClockType::now();

        auto cntrlPtr = controller.lock();
        assert(cntrlPtr &&
               cntrlPtr->status == NVMeControllerEnabled::Status::Enabled &&
               "NVMe Metric refresh requires enabled controller");
        assert(cntrlPtr->nvmeIntf &&
               "NVMe Metric refresh requires active MI interface");

        cntrlPtr->nvmeIntf->adminGetLogPage(
            cntrlPtr->nvmeCtrl, LID, 0, 0, 0,
            [weakSelf{std::move(this->weak_from_this())}, startTime,
             path{cntrlPtr->path}, id{getIdentifier()}, cb{std::move(cb)}](
                const std::error_code& ec, std::span<uint8_t> data) {
            auto self = std::dynamic_pointer_cast<
                ControllerLogPageMetric<LID, ClockType>>(weakSelf.lock());
            if (!self)
            {
                // TODO: error_level = INFO
                std::cerr << std::format(
                    "[{}, {}]metric released before callback\n", path, id);
                // The Scheduler will clear the invalid cache Task
                cb({}, 4096, true);
                return;
            }
            if (ec)
            {
                if (self->errorCount <
                    ControllerLogPageMetric<LID>::errorCountMax)
                {
                    // TODO: error_level = WARN
                    std::cerr << std::format(
                        "[{}, {}]fail to fresh log page at retry({})\n", path,
                        id, self->errorCount++);

                    // Schedule the retry after 1s
                    // TODO: costomize the retry delay for each log pages.
                    cb(std::make_error_code(std::errc::io_error), 4096, false);
                    return;
                }

                std::cerr << std::format(
                    "[{}, {}]retry exhausted to fresh log page\n", path, id);
                self->cacheValid = false;
                // Notify the MatrixStore of the for the invalid Cache
                self->completeCB(self);

                // Notify the RefreshCB with error code; the task will
                // be reschuduled after this->interval
                cb(std::make_error_code(std::errc::io_error), 4096, true);
                return;
            }
            self->errorCount = 0;
            self->cacheValid = true;
            std::get<0>(self->cache) = startTime;
            std::get<1>(self->cache) = ClockType::now();

            auto& cacheData = std::get<2>(self->cache);
            cacheData.clear();
            cacheData.insert(cacheData.begin(), data.begin(), data.end());

            // notify the MetricStore for completion
            self->completeCB(self);

            cb({}, data.size(), true);
        });
    }
    /* member variables */
    std::weak_ptr<NVMeControllerEnabled> controller;
    std::function<void(std::shared_ptr<MetricBase<ClockType>>)> completeCB;

    std::tuple<std::chrono::time_point<ClockType>,
               std::chrono::time_point<ClockType>, std::vector<uint8_t>>
        cache;
    bool cacheValid{false};
    unsigned errorCount{0};
    static constexpr unsigned errorCountMax = 5;
};
