/*
 * 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)
    {
    }

    sysrepo::ErrorCode operator()(
        sysrepo::Session sess,
        uint32_t /* sub_id */,
        std::string_view module_name,
        std::optional<std::string_view> /* sub_xpath */,
        sysrepo::Event event,
        uint32_t /* request_id */)
    {
        using namespace std::string_literals;
        if (event == sysrepo::Event::Change) {
            return sysrepo::ErrorCode::Ok;
        }

        for (const auto& it : sess.getChanges(("/"s + module_name.data() + ":*//.").c_str())) {
            auto xpath = it.node.path();
            std::optional<std::string> oldValue;
            std::optional<std::string> newValue;
            if (it.operation == sysrepo::ChangeOperation::Deleted) {
                oldValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
                    std::optional<std::string>{it.node.asTerm().valueStr()} :
                    std::nullopt;
            } else {
                oldValue = std::optional<std::string>{it.previousValue};
                newValue = it.node.schema().nodeType() == libyang::NodeType::Leaf || it.node.schema().nodeType() == libyang::NodeType::Leaflist ?
                    std::optional<std::string>{it.node.asTerm().valueStr()} :
                    std::nullopt;

            }
            std::optional<std::string> previousList;

            if (it.previousList) {
                previousList = std::string{*it.previousList};
            }

            m_recorder->write(it.operation, std::string{xpath}, oldValue, newValue, previousList);
        }

        return sysrepo::ErrorCode::Ok;
    }

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

Recorder::~Recorder() = default;

DataSupplier::~DataSupplier() = default;

SysrepoSubscription::SysrepoSubscription(const std::string& moduleName, Recorder* rec, sysrepo::Datastore ds)
    : m_subscription([&moduleName, &rec, ds] { // This is an immediately invoked lambda.
        return sysrepo::Connection{}.sessionStart(ds).onModuleChange(moduleName.c_str(),
                rec ? sysrepo::ModuleChangeCb{MyCallback{moduleName, rec}}
                : sysrepo::ModuleChangeCb{[](auto, auto, auto, auto, auto, auto) { return sysrepo::ErrorCode::Ok; }});
    }())
{
}

class OperationalDataCallback {
public:
    OperationalDataCallback(const DataSupplier& dataSupplier)
        : m_dataSupplier(dataSupplier)
    {
    }
    sysrepo::ErrorCode operator()(
            sysrepo::Session session,
            [[maybe_unused]] uint32_t subscriptionId,
            [[maybe_unused]] std::string_view moduleName,
            std::optional<std::string_view> subXPath,
            [[maybe_unused]] std::optional<std::string_view> requestXPath,
            [[maybe_unused]] uint32_t requestId,
            std::optional<libyang::DataNode>& output)
    {
        auto data = m_dataSupplier.get_data(subXPath->data());
        for (const auto& [p, v] : data) {
            if (!output) {
                output = session.getContext().newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
            } else {
                output->newPath(p.c_str(), v.type() == typeid(empty_) ? nullptr : leafDataToString(v).c_str());
            }
        }
        return sysrepo::ErrorCode::Ok;
    }

private:
    const DataSupplier& m_dataSupplier;
};

OperationalDataSubscription::OperationalDataSubscription(const std::string& moduleName, const std::string& path, const DataSupplier& dataSupplier)
    : m_subscription(sysrepo::Connection{}.sessionStart().onOperGet(moduleName.c_str(), OperationalDataCallback{dataSupplier}, path.c_str()))
{
}
