#include "api.hpp"

#include <fmt/printf.h>

namespace boot_time_monitor
{

namespace api
{

namespace btm = boot_time_monitor;

Api::~Api() = default;

void Api::SetNodeCheckpoint(const btm::NodeConfig& nodeConfig,
                            std::string_view checkpointName, int64_t wallTime,
                            int64_t selfMeasuredDuration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return;
    }

    it->second.get()->SetCheckpoint(checkpointName, wallTime,
                                    selfMeasuredDuration);
}

void Api::SetNodeDuration(const btm::NodeConfig& nodeConfig,
                          std::string_view durationName, int64_t duration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return;
    }

    it->second.get()->SetDuration(durationName, duration);
}

void Api::SetNodesCheckpointByTag(std::string_view tag,
                                  std::string_view checkpointName,
                                  int64_t wallTime,
                                  int64_t selfMeasuredDuration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    for (const auto& [config, node] : mResourceMap)
    {
        if (config.tag == tag)
        {
            node.get()->SetCheckpoint(checkpointName, wallTime,
                                      selfMeasuredDuration);
        }
    }
}

void Api::SetNodesDurationByTag(std::string_view tag,
                                std::string_view durationName, int64_t duration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    for (const auto& [config, node] : mResourceMap)
    {
        if (config.tag == tag)
        {
            node.get()->SetDuration(durationName, duration);
        }
    }
}

void Api::SetPSUCheckpoint(std::string_view checkpointName, int64_t wallTime,
                           int64_t selfMeasuredDuration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    // For "Power Supply Unit" checkpoint should broadcast to all nodes.
    for (const auto& [_, node] : mResourceMap)
    {
        node.get()->SetCheckpoint(checkpointName, wallTime,
                                  selfMeasuredDuration);
    }
}

void Api::SetPSUDuration(std::string_view durationName, int64_t duration)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    // For "Power Supply Unit" duration should broadcast to all nodes.
    for (const auto& [_, node] : mResourceMap)
    {
        node.get()->SetDuration(durationName, duration);
    }
}

void Api::NotifyNodeComplete(const btm::NodeConfig& nodeConfig)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return;
    }

    it->second.get()->MarkComplete();
}

void Api::NotifyNodesCompleteByTag(std::string_view tag)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    for (const auto& [config, node] : mResourceMap)
    {
        if (config.tag == tag)
        {
            node.get()->MarkComplete();
        }
    }
}

std::vector<std::tuple<std::string, int64_t, int64_t>>
    Api::GetNodeCheckpointList(const btm::NodeConfig& nodeConfig)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return {};
    }

    std::vector<std::tuple<std::string, int64_t, int64_t>> result;

    for (const auto& cp : it->second.get()->GetCheckpointCache())
    {
        result.emplace_back(std::make_tuple(cp.name, cp.wallTime, cp.monoTime));
    }

    return result;
}
std::vector<std::tuple<std::string, int64_t>>
    Api::GetNodeAdditionalDurations(const btm::NodeConfig& nodeConfig)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return {};
    }

    std::vector<std::tuple<std::string, int64_t>> result;

    for (const auto& dur : it->second.get()->GetDurationCache())
    {
        result.emplace_back(std::make_tuple(dur.name, dur.duration));
    }

    return result;
}

bool Api::IsNodeRebooting(const btm::NodeConfig& nodeConfig)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.find(nodeConfig);

    if (it == mResourceMap.end())
    {
        fmt::print("[{}] Failed to load `{}`. Skip it.\n", __FUNCTION__,
                   nodeConfig.nodeName);
        return false;
    }

    return it->second.get()->IsRebooting();
}

void Api::RegisterNode(const btm::NodeConfig& nodeConfig)
{
    std::lock_guard<std::mutex> guard(mApiMutex);
    auto it = mResourceMap.try_emplace(
        nodeConfig, std::make_unique<resource::File>(nodeConfig.nodeName));

    if (!it.second)
    {
        fmt::print(
            "[{}] Failed to register `{}` due to the key duplicated. Skip it.\n",
            __FUNCTION__, nodeConfig.nodeName);
    }
}
} // namespace api
} // namespace boot_time_monitor
