/*
 * Copyright (C) 2016-2019 CESNET, https://photonics.cesnet.cz/
 *
 * Written by Jan Kundrát <jan.kundrat@cesnet.cz>
 *
*/

#include "trompeloeil_doctest.h"
#include <boost/algorithm/string/predicate.hpp>
#include <map>
#include <sysrepo-cpp/Session.hpp>
#include "test_log_setup.h"
#include "utils/sysrepo.h"

/** @short Return a subtree from sysrepo, compacting the XPath */
auto dataFromSysrepo(const std::shared_ptr<sysrepo::Session>& session, const std::string& xpath)
{
    spdlog::get("main")->error("dataFrom {}", xpath);
    std::map<std::string, std::string> res;
    auto vals = session->get_items((xpath + "//*").c_str());
    REQUIRE(!!vals);
    for (size_t i = 0; i < vals->val_cnt(); ++i) {
        const auto& v = vals->val(i);
        const auto briefXPath = std::string(v->xpath()).substr(boost::algorithm::ends_with(xpath, ":*") ? xpath.size() - 1 : xpath.size());
        res.emplace(briefXPath, v->val_to_string());
    }
    return res;
}

/** @short Execute an RPC or action, return result, compacting the XPath. The rpcPath and input gets concatenated. */
auto rpcFromSysrepo(const std::shared_ptr<sysrepo::Session>& session, const std::string& rpcPath, std::map<std::string, std::string> input)
{
    spdlog::get("main")->info("rpcFromSysrepo {}", rpcPath);
    auto inputNode = std::make_shared<libyang::Data_Node>(session->get_context(), rpcPath.c_str(), nullptr, LYD_ANYDATA_CONSTSTRING, 0);
    for (const auto& [k, v] : input) {
        inputNode->new_path(session->get_context(), (rpcPath + "/" + k).c_str(), v.c_str(), LYD_ANYDATA_CONSTSTRING, 0);
    }

    auto output = session->rpc_send(inputNode);
    REQUIRE(!!output);

    // Sysrepo returns a top-level node. I need the node that contains the action and iterate over that instead of the
    // top-level node.
    auto actualOutput = output->find_path(rpcPath.c_str())->data().front();

    std::map<std::string, std::string> res;
    for (const auto& node : actualOutput->tree_dfs()) {
        if (node->schema()->nodetype() == LYS_LEAF) {
            auto leaf = std::make_shared<libyang::Data_Node_Leaf_List>(node);
            auto path = node->path();
            const auto briefXPath = path.substr(rpcPath.size());
            res.emplace(briefXPath, leaf->value_str());
        }
    }
    return res;
}

/** @short Return a subtree from specified sysrepo's datastore, compacting the XPath*/
auto dataFromSysrepo(const std::shared_ptr<sysrepo::Session>& session, const std::string& xpath, sr_datastore_t datastore)
{
    sr_datastore_t oldDatastore = session->session_get_ds();
    session->session_switch_ds(datastore);

    auto res = dataFromSysrepo(session, xpath);

    session->session_switch_ds(oldDatastore);
    return res;
}

#define TEST_SYSREPO_INIT                                     \
    auto srConn = std::make_shared<sysrepo::Connection>();    \
    auto srSess = std::make_shared<sysrepo::Session>(srConn); \
    auto srSubs = std::make_shared<sysrepo::Subscribe>(srSess);

#define TEST_SYSREPO_INIT_CLIENT                                  \
    auto clientConn = std::make_shared<sysrepo::Connection>();    \
    auto client = std::make_shared<sysrepo::Session>(clientConn); \
    auto subscription = std::make_shared<sysrepo::Subscribe>(client);
