/*
 * 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,
            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());
}
