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

#include <cstring>
#include <libyang/Tree_Data.hpp>
#include <mutex>
extern "C" {
#include <nc_client.h>
}
#include <sstream>
#include "UniqueResource.hpp"
#include "netconf-client.hpp"

namespace libnetconf {

namespace impl {

static client::LogCb logCallback;

static void logViaCallback(NC_VERB_LEVEL level, const char* message)
{
    logCallback(level, message);
}


/** @short Initialization of the libnetconf2 library client

Just a safe wrapper over nc_client_init and nc_client_destroy, really.
*/
class ClientInit {
    ClientInit()
    {
        nc_client_init();
    }

    ~ClientInit()
    {
        nc_client_destroy();
    }

public:
    static ClientInit& instance()
    {
        static ClientInit lib;
        return lib;
    }

    ClientInit(const ClientInit&) = delete;
    ClientInit(ClientInit&&) = delete;
    ClientInit& operator=(const ClientInit&) = delete;
    ClientInit& operator=(ClientInit&&) = delete;
};

static std::mutex clientOptions;

inline void custom_free_nc_reply_data(nc_reply_data* reply)
{
    nc_reply_free(reinterpret_cast<nc_reply*>(reply));
}
inline void custom_free_nc_reply_error(nc_reply_error* reply)
{
    nc_reply_free(reinterpret_cast<nc_reply*>(reply));
}

char* ssh_auth_interactive_cb(const char* auth_name, const char* instruction, const char* prompt, int echo, void* priv)
{
    const auto cb = static_cast<const client::KbdInteractiveCb*>(priv);
    auto res = (*cb)(auth_name, instruction, prompt, echo);
    return ::strdup(res.c_str());
}

template <typename Type> using deleter_type_for = void (*)(Type*);
template <typename Type> deleter_type_for<Type> const deleter_for;

template <> const auto deleter_for<nc_rpc> = nc_rpc_free;
template <> const auto deleter_for<nc_reply> = nc_reply_free;
template <> const auto deleter_for<nc_reply_data> = custom_free_nc_reply_data;
template <> const auto deleter_for<nc_reply_error> = custom_free_nc_reply_error;

template <typename T>
using unique_ptr_for = std::unique_ptr<T, decltype(deleter_for<T>)>;

template <typename T>
auto guarded(T* ptr)
{
    return unique_ptr_for<T>(ptr, deleter_for<T>);
}

unique_ptr_for<struct nc_reply> do_rpc(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
{
    uint64_t msgid;
    NC_MSG_TYPE msgtype;

    msgtype = nc_send_rpc(session->session_internal(), rpc.get(), 1000, &msgid);
    if (msgtype == NC_MSG_ERROR) {
        throw std::runtime_error{"Failed to send RPC"};
    }
    if (msgtype == NC_MSG_WOULDBLOCK) {
        throw std::runtime_error{"Timeout sending an RPC"};
    }

    struct nc_reply* raw_reply;
    while (true) {
        msgtype = nc_recv_reply(session->session_internal(), rpc.get(), msgid, 20000, LYD_OPT_DESTRUCT | LYD_OPT_NOSIBLINGS, &raw_reply);
        auto reply = guarded(raw_reply);
        raw_reply = nullptr;

        switch (msgtype) {
        case NC_MSG_ERROR:
            throw std::runtime_error{"Failed to receive an RPC reply"};
        case NC_MSG_WOULDBLOCK:
            throw std::runtime_error{"Timed out waiting for RPC reply"};
        case NC_MSG_REPLY_ERR_MSGID:
            throw std::runtime_error{"Received a wrong reply -- msgid mismatch"};
        case NC_MSG_NOTIF:
            continue;
        default:
            return reply;
        }
    }
    __builtin_unreachable();
}

client::ReportedError make_error(unique_ptr_for<struct nc_reply>&& reply)
{
    if (reply->type != NC_RPL_ERROR) {
        throw std::logic_error{"Cannot extract an error from a non-error server reply"};
    }

    auto errorReply = guarded(reinterpret_cast<struct nc_reply_error*>(reply.release()));

    // TODO: capture the error details, not just that human-readable string
    std::ostringstream ss;
    ss << "Server error:" << std::endl;
    for (uint32_t i = 0; i < errorReply->count; ++i) {
        const auto e = errorReply->err[i];
        ss << " #" << i << ": " << e.message;
        if (e.path) {
            ss << " (XPath " << e.path << ")";
        }
        ss << std::endl;
    }
    return client::ReportedError{ss.str()};
}

std::optional<unique_ptr_for<struct nc_reply_data>> do_rpc_data_or_ok(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
{
    auto x = do_rpc(session, std::move(rpc));

    switch (x->type) {
    case NC_RPL_DATA:
        return guarded(reinterpret_cast<struct nc_reply_data*>(x.release()));
    case NC_RPL_OK:
        return std::nullopt;
    case NC_RPL_ERROR:
        throw make_error(std::move(x));
    default:
        throw std::runtime_error{"Unhandled reply type"};
    }
}

unique_ptr_for<struct nc_reply_data> do_rpc_data(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
{
    auto x = do_rpc_data_or_ok(session, std::move(rpc));
    if (!x) {
        throw std::runtime_error{"Received OK instead of a data reply"};
    }
    return std::move(*x);
}

void do_rpc_ok(client::Session* session, unique_ptr_for<struct nc_rpc>&& rpc)
{
    auto x = do_rpc_data_or_ok(session, std::move(rpc));
    if (x) {
        throw std::runtime_error{"Unexpected DATA reply"};
    }
}

std::shared_ptr<libyang::Data_Node> do_get(client::Session* session, unique_ptr_for<nc_rpc> rpc)
{
    auto reply = impl::do_rpc_data(session, std::move(rpc));
    auto dataNode = libyang::create_new_Data_Node(reply->data);
    // TODO: can we do without copying?
    // If we just default-construct a new node (or use the create_new_Data_Node) and then set reply->data to nullptr,
    // there are mem leaks and even libnetconf2 complains loudly.
    return dataNode ? dataNode->dup_withsiblings(1) : nullptr;
}
}

namespace client {

void setLogLevel(NC_VERB_LEVEL level)
{
    nc_verbosity(level);
}

void setLogCallback(const client::LogCb& callback)
{
    impl::logCallback = callback;
    nc_set_print_clb(impl::logViaCallback);
}

struct nc_session* Session::session_internal()
{
    return m_session;
}

libyang::S_Context Session::libyangContext()
{
    return std::make_shared<libyang::Context>(nc_session_get_ctx(m_session), nullptr);
}

Session::Session(struct nc_session* session)
    : m_session(session)
{
    impl::ClientInit::instance();
}

Session::~Session()
{
    ::nc_session_free(m_session, nullptr);
}

std::unique_ptr<Session> Session::connectPubkey(const std::string& host, const uint16_t port, const std::string& user, const std::string& pubPath, const std::string& privPath)
{
    impl::ClientInit::instance();

    {
        // FIXME: this is still horribly not enough. libnetconf *must* provide us with something better.
        std::lock_guard lk(impl::clientOptions);
        nc_client_ssh_set_username(user.c_str());
        nc_client_ssh_set_auth_pref(NC_SSH_AUTH_PUBLICKEY, 5);
        nc_client_ssh_add_keypair(pubPath.c_str(), privPath.c_str());
    }
    auto session = std::make_unique<Session>(nc_connect_ssh(host.c_str(), port, nullptr));
    if (!session->m_session) {
        throw std::runtime_error{"nc_connect_ssh failed"};
    }
    return session;
}

std::unique_ptr<Session> Session::connectKbdInteractive(const std::string& host, const uint16_t port, const std::string& user, const KbdInteractiveCb& callback)
{
    impl::ClientInit::instance();

    std::lock_guard lk(impl::clientOptions);
    auto cb_guard = make_unique_resource([user, &callback]() {
        nc_client_ssh_set_username(user.c_str());
        nc_client_ssh_set_auth_pref(NC_SSH_AUTH_INTERACTIVE, 5);
        nc_client_ssh_set_auth_interactive_clb(impl::ssh_auth_interactive_cb, static_cast<void *>(&const_cast<KbdInteractiveCb&>(callback)));
    }, []() {
        nc_client_ssh_set_auth_interactive_clb(nullptr, nullptr);
        nc_client_ssh_set_username(nullptr);
    });

    auto session = std::make_unique<Session>(nc_connect_ssh(host.c_str(), port, nullptr));
    if (!session->m_session) {
        throw std::runtime_error{"nc_connect_ssh failed"};
    }
    return session;
}

std::unique_ptr<Session> Session::connectFd(const int source, const int sink)
{
    impl::ClientInit::instance();

    auto session = std::make_unique<Session>(nc_connect_inout(source, sink, nullptr));
    if (!session->m_session) {
        throw std::runtime_error{"nc_connect_inout failed"};
    }
    return session;
}

std::unique_ptr<Session> Session::connectSocket(const std::string& path)
{
    impl::ClientInit::instance();

    auto session = std::make_unique<Session>(nc_connect_unix(path.c_str(), nullptr));
    if (!session->m_session) {
        throw std::runtime_error{"nc_connect_unix failed"};
    }
    return session;
}

std::vector<std::string_view> Session::capabilities() const
{
    std::vector<std::string_view> res;
    auto caps = nc_session_get_cpblts(m_session);
    while (*caps) {
        res.emplace_back(*caps);
        ++caps;
    }
    return res;
}

std::shared_ptr<libyang::Data_Node> Session::get(const std::optional<std::string>& filter)
{
    auto rpc = impl::guarded(nc_rpc_get(filter ? filter->c_str() : nullptr, NC_WD_ALL, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create get RPC");
    }
    return impl::do_get(this, std::move(rpc));
}

const char* datastoreToString(NmdaDatastore datastore)
{
    switch (datastore) {
    case NmdaDatastore::Startup:
        return "ietf-datastores:startup";
    case NmdaDatastore::Running:
        return "ietf-datastores:running";
    case NmdaDatastore::Candidate:
        return "ietf-datastores:candidate";
    case NmdaDatastore::Operational:
        return "ietf-datastores:operational";
    }
    __builtin_unreachable();
}

std::shared_ptr<libyang::Data_Node> Session::getData(const NmdaDatastore datastore, const std::optional<std::string>& filter)
{
    auto rpc = impl::guarded(nc_rpc_getdata(datastoreToString(datastore), filter ? filter->c_str() : nullptr, nullptr, nullptr, 0, 0, 0, 0, NC_WD_ALL, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create get RPC");
    }
    return impl::do_get(this, std::move(rpc));
}

void Session::editData(const NmdaDatastore datastore, const std::string& data)
{
    auto rpc = impl::guarded(nc_rpc_editdata(datastoreToString(datastore), NC_RPC_EDIT_DFLTOP_MERGE, data.c_str(), NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create get RPC");
    }
    return impl::do_rpc_ok(this, std::move(rpc));
}

std::string Session::getSchema(const std::string_view identifier, const std::optional<std::string_view> version)
{
    auto rpc = impl::guarded(nc_rpc_getschema(identifier.data(), version ? version.value().data() : nullptr, nullptr, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create get-schema RPC");
    }
    auto reply = impl::do_rpc_data(this, std::move(rpc));

    auto node = libyang::create_new_Data_Node(reply->data)->dup_withsiblings(1);
    auto set = node->find_path("data");
    for (auto node : set->data()) {
        if (node->schema()->nodetype() == LYS_ANYXML) {
            libyang::Data_Node_Anydata anydata(node);
            return anydata.value().str;
        }
    }
    throw std::runtime_error("Got a reply to get-schema, but it didn't contain the required schema");
}

std::shared_ptr<libyang::Data_Node> Session::getConfig(const NC_DATASTORE datastore, const std::optional<const std::string> filter)
{
    auto rpc = impl::guarded(nc_rpc_getconfig(datastore, filter ? filter->c_str() : nullptr, NC_WD_ALL, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create get-config RPC");
    }
    return impl::do_get(this, std::move(rpc));
}

void Session::editConfig(const NC_DATASTORE datastore,
                         const NC_RPC_EDIT_DFLTOP defaultOperation,
                         const NC_RPC_EDIT_TESTOPT testOption,
                         const NC_RPC_EDIT_ERROPT errorOption,
                         const std::string& data)
{
    auto rpc = impl::guarded(nc_rpc_edit(datastore, defaultOperation, testOption, errorOption, data.c_str(), NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create edit-config RPC");
    }
    impl::do_rpc_ok(this, std::move(rpc));
}

void Session::copyConfigFromString(const NC_DATASTORE target, const std::string& data)
{
    auto rpc = impl::guarded(nc_rpc_copy(target, nullptr, target /* yeah, cannot be 0... */, data.c_str(), NC_WD_UNKNOWN, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create copy-config RPC");
    }
    impl::do_rpc_ok(this, std::move(rpc));
}

void Session::commit()
{
    auto rpc = impl::guarded(nc_rpc_commit(0, /* "Optional confirm timeout" how do you optional an uint32_t? */ 0, nullptr, nullptr, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create commit RPC");
    }
    impl::do_rpc_ok(this, std::move(rpc));
}

void Session::discard()
{
    auto rpc = impl::guarded(nc_rpc_discard());
    if (!rpc) {
        throw std::runtime_error("Cannot create discard RPC");
    }
    impl::do_rpc_ok(this, std::move(rpc));
}

std::shared_ptr<libyang::Data_Node> Session::rpc_or_action(const std::string& xmlData)
{
    auto rpc = impl::guarded(nc_rpc_act_generic_xml(xmlData.c_str(), NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create generic RPC");
    }
    auto reply = impl::do_rpc_data_or_ok(this, std::move(rpc));
    if (reply) {
        auto dataNode = libyang::create_new_Data_Node((*reply)->data);
        return dataNode->dup_withsiblings(1);
    } else {
        return nullptr;
    }
}

void Session::copyConfig(const NC_DATASTORE source, const NC_DATASTORE destination)
{
    auto rpc = impl::guarded(nc_rpc_copy(destination, nullptr, source, nullptr, NC_WD_UNKNOWN, NC_PARAMTYPE_CONST));
    if (!rpc) {
        throw std::runtime_error("Cannot create copy-config RPC");
    }
    impl::do_rpc_ok(this, std::move(rpc));
}

ReportedError::ReportedError(const std::string& what)
    : std::runtime_error(what)
{
}

ReportedError::~ReportedError() = default;
}
}
