/*
 * Copyright (C) 2018 CESNET, https://photonics.cesnet.cz/
 * Copyright (C) 2018 FIT CVUT, https://fit.cvut.cz/
 *
 * Written by Václav Kubernát <kubervac@fit.cvut.cz>
 *
*/

#include <experimental/iterator>
#include <sstream>
#include <sysrepo-cpp/Session.hpp>
#include "sysrepo_subscription.hpp"
#include "utils.hpp"


class MyCallback {
public:
    MyCallback(const std::string& moduleName, Recorder* rec)
        : m_moduleName(moduleName)
        , m_recorder(rec)
    {
    }

    int operator()(
        sysrepo::S_Session sess,
        [[maybe_unused]] const char* module_name,
        [[maybe_unused]] const char* xpath,
        [[maybe_unused]] sr_event_t event,
        [[maybe_unused]] uint32_t request_id)
    {
        using namespace std::string_literals;
        if (event == SR_EV_CHANGE) {
            return SR_ERR_OK;
        }

        auto it = sess->get_changes_iter(("/"s + module_name + ":*//.").c_str());

        while (auto change = sess->get_change_next(it)) {
            auto xpath = (change->new_val() ? change->new_val() : change->old_val())->xpath();

            auto oldValue = change->old_val() ? std::optional{change->old_val()->val_to_string()} : std::nullopt;
            auto newValue = change->new_val() ? std::optional{change->new_val()->val_to_string()} : std::nullopt;
            m_recorder->write(xpath, oldValue, newValue);
        }

        return SR_ERR_OK;
    }

private:
    std::string m_moduleName;
    Recorder* m_recorder;
};

Recorder::~Recorder() = default;

DataSupplier::~DataSupplier() = default;

SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec)
    : m_connection(std::make_shared<sysrepo::Connection>())
{
    m_session = std::make_shared<sysrepo::Session>(m_connection);
    m_subscription = std::make_shared<sysrepo::Subscribe>(m_session);
    sysrepo::ModuleChangeCb cb;
    if (rec) {
        cb = MyCallback{moduleName, rec};
    } else {
        cb = [](auto, auto, auto, auto, auto) { return SR_ERR_OK; };
    }

    m_subscription->module_change_subscribe(moduleName.c_str(), cb);
}


struct leafDataToSysrepoVal {
    leafDataToSysrepoVal(sysrepo::S_Val v, const std::string& xpath)
        : v(v)
        , xpath(xpath)
    {
    }

    void operator()(const binary_& what)
    {
        v->set(xpath.c_str(), what.m_value.c_str(), SR_BINARY_T);
    }

    void operator()(const enum_& what)
    {
        v->set(xpath.c_str(), what.m_value.c_str(), SR_ENUM_T);
    }

    void operator()(const identityRef_& what)
    {
        v->set(xpath.c_str(), (what.m_prefix->m_name + what.m_value).c_str(), SR_IDENTITYREF_T);
    }

    void operator()(const empty_)
    {
        v->set(xpath.c_str(), nullptr, SR_LEAF_EMPTY_T);
    }

    void operator()(const std::string& what)
    {
        v->set(xpath.c_str(), what.c_str());
    }

    void operator()(const bits_& what)
    {
        std::stringstream ss;
        std::copy(what.m_bits.begin(), what.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
        v->set(xpath.c_str(), ss.str().c_str());
    }

    template <typename Type>
    void operator()(const Type what)
    {
        v->set(xpath.c_str(), what);
    }

    void operator()([[maybe_unused]] const special_ what)
    {
        throw std::logic_error("Attempted to create a SR val from a special_ value");
    }

    ::sysrepo::S_Val v;
    std::string xpath;
};

class OperationalDataCallback {
public:
    OperationalDataCallback(const DataSupplier& dataSupplier)
        : m_dataSupplier(dataSupplier)
    {
    }
    int operator()(
        [[maybe_unused]] sysrepo::S_Session sess,
        [[maybe_unused]] const char* module_name,
        const char* path,
        [[maybe_unused]] const char* request_xpath,
        [[maybe_unused]] uint32_t request_id,
        libyang::S_Data_Node& parent)
    {
        auto data = m_dataSupplier.get_data(path);
        libyang::S_Data_Node res;
        for (const auto& [p, v] : data) {
            if (!res) {
                res = std::make_shared<libyang::Data_Node>(
                    sess->get_context(),
                    p.c_str(),
                    v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
                    LYD_ANYDATA_CONSTSTRING,
                    0);
            } else {
                res->new_path(
                    sess->get_context(),
                    p.c_str(),
                    v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str(),
                    LYD_ANYDATA_CONSTSTRING,
                    0);
            }
        }
        parent = res;
        return SR_ERR_OK;
    }

private:
    const DataSupplier& m_dataSupplier;
};

OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
    : m_connection(std::make_shared<sysrepo::Connection>())
    , m_session(std::make_shared<sysrepo::Session>(m_connection))
    , m_subscription(std::make_shared<sysrepo::Subscribe>(m_session))
{
    m_subscription->oper_get_items_subscribe(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str());
}
