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

#include "NVMeCache.hpp"
#include "NVMeController.hpp"
#include "NVMeVolume.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, ClockType>::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;
};

/**
 * Metric implementation for Identify info
 */
template <nvme_identify_cns CNS, class ClockType>
class IdentifyMetric : public MetricBase<ClockType>
{
  public:
    template <class T>
        requires((CNS == NVME_IDENTIFY_CNS_CTRL &&
                  std::is_base_of_v<NVMeControllerEnabled, T>) ||
                 (CNS == NVME_IDENTIFY_CNS_NS &&
                  std::is_base_of_v<NVMeVolume, T>))
    IdentifyMetric(std::shared_ptr<T> resource,
                   std::shared_ptr<Scheduler<ClockType>> scheduler,
                   ClockType::duration interval,
                   std::function<void(std::shared_ptr<MetricBase<ClockType>>)>&&
                       completeCB) :
        MetricBase<ClockType>(scheduler, interval),
        completeCB(std::move(completeCB))
    {
        if constexpr (CNS == NVME_IDENTIFY_CNS_CTRL)
        {
            controller = resource;
            namespaceId = 0;
        }
        else if constexpr (CNS == NVME_IDENTIFY_CNS_NS)
        {
            auto subsys = resource->subsys.lock();
            assert(subsys &&
                   "Fail to construct NS Identify Metric on expired subsystem");
            controller = subsys->getPrimaryController();
            resource->namespaceId();
        }
        else
        {
            static_assert(false, "unsupported CNS for IdentifyMetric");
        }
    }

    /* interface overrides */
    inline static constexpr std::string_view identifyIdentifier() noexcept
    {
        return "IdentifyMetric";
    }
    constexpr std::string_view getIdentifier() const noexcept override
    {
        return identifyIdentifier();
    }

    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->adminIdentify(
            cntrlPtr->nvmeCtrl, CNS, namespaceId,
            0 /* CNTID will not be used for CNS = 00h/01h */,
            [weakSelf{std::move(this->weak_from_this())}, startTime,
             path{cntrlPtr->path}, id{getIdentifier()}, cb{std::move(cb)}](
                const nvme_ex_ptr& ex, std::span<uint8_t> data) {
            auto self =
                std::dynamic_pointer_cast<IdentifyMetric<CNS, 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 (ex)
            {
                if (self->errorCount <
                    IdentifyMetric<CNS, ClockType>::errorCountMax)
                {
                    // TODO: error_level = WARN
                    std::cerr << std::format(
                        "[{}, {}]fail to fresh identify at retry({}): {}\n",
                        path, id, self->errorCount++, ex->description());

                    // Schedule the retry after 1s
                    cb(std::make_error_code(std::errc::io_error), 4096, false);
                    return;
                }
                std::cerr << std::format(
                    "[{}, {}]retry exhausted to fresh identify: {}\n", path, id,
                    ex->description());
                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;
    uint32_t namespaceId;

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