/*
 * 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 <libyang/Tree_Data.hpp>
#include <libyang/Tree_Schema.hpp>
#include <sysrepo-cpp/Session.hpp>
#include <sstream>
#include "libyang_utils.hpp"
#include "sysrepo_access.hpp"
#include "utils.hpp"
#include "yang_schema.hpp"

leaf_data_ leafValueFromVal(const sysrepo::S_Val& value)
{
    using namespace std::string_literals;
    switch (value->type()) {
    case SR_INT8_T:
        return value->data()->get_int8();
    case SR_UINT8_T:
        return value->data()->get_uint8();
    case SR_INT16_T:
        return value->data()->get_int16();
    case SR_UINT16_T:
        return value->data()->get_uint16();
    case SR_INT32_T:
        return value->data()->get_int32();
    case SR_UINT32_T:
        return value->data()->get_uint32();
    case SR_INT64_T:
        return value->data()->get_int64();
    case SR_UINT64_T:
        return value->data()->get_uint64();
    case SR_BOOL_T:
        return value->data()->get_bool();
    case SR_STRING_T:
        return std::string(value->data()->get_string());
    case SR_ENUM_T:
        return enum_{std::string(value->data()->get_enum())};
    case SR_IDENTITYREF_T:
    {
        auto pair = splitModuleNode(value->data()->get_identityref());
        return identityRef_{*pair.first, pair.second};
    }
    case SR_BINARY_T:
        return binary_{value->data()->get_binary()};
    case SR_LEAF_EMPTY_T:
        return empty_{};
    case SR_DECIMAL64_T:
        return value->data()->get_decimal64();
    case SR_CONTAINER_T:
        return special_{SpecialValue::Container};
    case SR_CONTAINER_PRESENCE_T:
        return special_{SpecialValue::PresenceContainer};
    case SR_LIST_T:
        return special_{SpecialValue::List};
    case SR_BITS_T:
    {
        bits_ res;
        std::istringstream ss(value->data()->get_bits());
        while (!ss.eof()) {
            std::string bit;
            ss >> bit;
            res.m_bits.insert(bit);
        }
        return res;

    }
    default: // TODO: implement all types
        return value->val_to_string();
    }
}

struct valFromValue : boost::static_visitor<sysrepo::S_Val> {
    sysrepo::S_Val operator()(const enum_& value) const
    {
        return std::make_shared<sysrepo::Val>(value.m_value.c_str(), SR_ENUM_T);
    }

    sysrepo::S_Val operator()(const binary_& value) const
    {
        return std::make_shared<sysrepo::Val>(value.m_value.c_str(), SR_BINARY_T);
    }

    sysrepo::S_Val operator()(const empty_) const
    {
        return std::make_shared<sysrepo::Val>(nullptr, SR_LEAF_EMPTY_T);
    }

    sysrepo::S_Val operator()(const identityRef_& value) const
    {
        auto res = value.m_prefix ? (value.m_prefix.value().m_name + ":" + value.m_value) : value.m_value;
        return std::make_shared<sysrepo::Val>(res.c_str(), SR_IDENTITYREF_T);
    }

    sysrepo::S_Val operator()(const special_& value) const
    {
        throw std::runtime_error("Tried constructing S_Val from a " + specialValueToString(value));
    }

    sysrepo::S_Val operator()(const std::string& value) const
    {
        return std::make_shared<sysrepo::Val>(value.c_str());
    }

    sysrepo::S_Val operator()(const bits_& value) const
    {
        std::stringstream ss;
        std::copy(value.m_bits.begin(), value.m_bits.end(), std::experimental::make_ostream_joiner(ss, " "));
        return std::make_shared<sysrepo::Val>(ss.str().c_str(), SR_BITS_T);
    }

    template <typename T>
    sysrepo::S_Val operator()(const T& value) const
    {
        return std::make_shared<sysrepo::Val>(value);
    }
};

struct updateSrValFromValue : boost::static_visitor<void> {
    std::string xpath;
    sysrepo::S_Val v;
    updateSrValFromValue(const std::string& xpath, sysrepo::S_Val v)
        : xpath(xpath)
        , v(v)
    {
    }

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

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

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

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

    void operator()(const special_& value) const
    {
        switch (value.m_value) {
        case SpecialValue::PresenceContainer:
            v->set(xpath.c_str(), nullptr, SR_CONTAINER_PRESENCE_T);
            break;
        case SpecialValue::List:
            v->set(xpath.c_str(), nullptr, SR_LIST_T);
            break;
        default:
            throw std::runtime_error("Tried constructing S_Val from a " + specialValueToString(value));
        }
    }

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

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

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

SysrepoAccess::~SysrepoAccess() = default;

sr_datastore_t toSrDatastore(Datastore datastore)
{
    switch (datastore) {
    case Datastore::Running:
        return SR_DS_RUNNING;
    case Datastore::Startup:
        return SR_DS_STARTUP;
    }
    __builtin_unreachable();
}

SysrepoAccess::SysrepoAccess(const std::string& appname, const Datastore datastore)
    : m_connection(new sysrepo::Connection(appname.c_str()))
    , m_schema(new YangSchema())
{
    try {
        m_session = std::make_shared<sysrepo::Session>(m_connection, toSrDatastore(datastore));
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }

    // If fetching a submodule, sysrepo::Session::get_schema will determine the revision from the main module.
    // That's why submoduleRevision is ignored.
    m_schema->registerModuleCallback([this](const char* moduleName, const char* revision, const char* submodule, [[maybe_unused]] const char* submoduleRevision) {
        return fetchSchema(moduleName, revision, submodule);
    });

    for (const auto& it : listSchemas()) {
        if (it->implemented()) {
            m_schema->loadModule(it->module_name());
            for (unsigned int i = 0; i < it->enabled_feature_cnt(); i++) {
                m_schema->enableFeature(it->module_name(), it->enabled_features(i));
            }
        }
    }
}

DatastoreAccess::Tree SysrepoAccess::getItems(const std::string& path) const
{
    using namespace std::string_literals;
    Tree res;

    auto fillMap = [this, &res](auto items) {
        if (!items) {
            return;
        }
        for (unsigned int i = 0; i < items->val_cnt(); i++) {
            auto value = leafValueFromVal(items->val(i));
            if (m_schema->nodeType(items->val(i)->xpath()) == yang::NodeTypes::LeafList) {
                res.emplace_back(items->val(i)->xpath(), special_{SpecialValue::LeafList});
                std::string leafListPath = items->val(i)->xpath();
                while (i < items->val_cnt() && leafListPath == items->val(i)->xpath()) {
                    auto leafListValue = leafDataToString(leafValueFromVal(items->val(i)));
                    res.emplace_back(items->val(i)->xpath() + "[.="s + escapeListKeyString(leafListValue) + "]", leafListValue);
                    i++;
                }
            } else {
                res.emplace_back(items->val(i)->xpath(), value);
            }
        }
    };

    try {
        if (path == "/") {
            // Sysrepo doesn't have a root node ("/"), so we take all top-level nodes from all schemas
            auto schemas = m_session->list_schemas();
            for (unsigned int i = 0; i < schemas->schema_cnt(); i++) {
                fillMap(m_session->get_items(("/"s + schemas->schema(i)->module_name() + ":*//.").c_str()));
            }
        } else {
            fillMap(m_session->get_items((path + "//.").c_str()));
        }
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
    return res;
}

void SysrepoAccess::setLeaf(const std::string& path, leaf_data_ value)
{
    try {
        m_session->set_item(path.c_str(), boost::apply_visitor(valFromValue(), value));
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
}

void SysrepoAccess::createItem(const std::string& path)
{
    try {
        m_session->set_item(path.c_str());
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
}

void SysrepoAccess::deleteItem(const std::string& path)
{
    try {
        m_session->delete_item(path.c_str());
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
}

struct impl_toSrMoveOp {
    sr_move_position_t operator()(yang::move::Absolute& absolute)
    {
        return absolute == yang::move::Absolute::Begin ? SR_MOVE_FIRST : SR_MOVE_LAST;
    }
    sr_move_position_t operator()(yang::move::Relative& relative)
    {
        return relative.m_position == yang::move::Relative::Position::After ? SR_MOVE_AFTER : SR_MOVE_BEFORE;
    }
};

sr_move_position_t toSrMoveOp(std::variant<yang::move::Absolute, yang::move::Relative> move)
{
    return std::visit(impl_toSrMoveOp{}, move);
}

void SysrepoAccess::moveItem(const std::string& source, std::variant<yang::move::Absolute, yang::move::Relative> move)
{
    std::string destPathStr;
    if (std::holds_alternative<yang::move::Relative>(move)) {
        auto relative = std::get<yang::move::Relative>(move);
        if (m_schema->nodeType(source) == yang::NodeTypes::LeafList) {
            destPathStr = stripLeafListValueFromPath(source) + "[.='" + leafDataToString(relative.m_path.at(".")) + "']";
        } else {
            destPathStr = stripLastListInstanceFromPath(source) + instanceToString(relative.m_path, m_schema->dataNodeFromPath(source)->node_module()->name());
        }
    }
    m_session->move_item(source.c_str(), toSrMoveOp(move), destPathStr.c_str());
}

void SysrepoAccess::commitChanges()
{
    try {
        m_session->commit();
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
}

void SysrepoAccess::discardChanges()
{
    try {
        m_session->discard_changes();
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
}

namespace {
std::shared_ptr<sysrepo::Vals> toSrVals(const std::string& path, const DatastoreAccess::Tree& input)
{
    auto res = std::make_shared<sysrepo::Vals>(input.size());
    {
        size_t i = 0;
        for (const auto& [k, v] : input) {
            boost::apply_visitor(updateSrValFromValue(joinPaths(path, k), res->val(i)), v);
            ++i;
        }
    }
    return res;
}

DatastoreAccess::Tree toTree(const std::string& path, const std::shared_ptr<sysrepo::Vals>& output)
{
    DatastoreAccess::Tree res;
    for (size_t i = 0; i < output->val_cnt(); ++i) {
        const auto& v = output->val(i);
        res.emplace_back(std::string(v->xpath()).substr(joinPaths(path, "/").size()), leafValueFromVal(v));
    }
    return res;
}
}

DatastoreAccess::Tree SysrepoAccess::executeRpc(const std::string &path, const Tree &input)
{
    auto srInput = toSrVals(path, input);
    auto output = m_session->rpc_send(path.c_str(), srInput);
    return toTree(path, output);
}

DatastoreAccess::Tree SysrepoAccess::executeAction(const std::string& path, const Tree& input)
{
    auto srInput = toSrVals(path, input);
    auto output = m_session->action_send(path.c_str(), srInput);
    return toTree(path, output);
}

void SysrepoAccess::copyConfig(const Datastore source, const Datastore destination)
{
    m_session->copy_config(nullptr, toSrDatastore(source), toSrDatastore(destination));
    if (destination == Datastore::Running) {
        m_session->refresh();
    }
}

std::string SysrepoAccess::fetchSchema(const char* module, const char* revision, const char* submodule)
{
    std::string schema;
    try {
        schema = m_session->get_schema(module, revision, submodule, SR_SCHEMA_YANG);
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }

    if (schema.empty()) {
        throw std::runtime_error(std::string("Module ") + module + " not available");
    }

    return schema;
}

std::vector<std::shared_ptr<sysrepo::Yang_Schema>> SysrepoAccess::listSchemas()
{
    std::vector<sysrepo::S_Yang_Schema> res;
    std::shared_ptr<sysrepo::Yang_Schemas> schemas;
    try {
        schemas = m_session->list_schemas();
    } catch (sysrepo::sysrepo_exception& ex) {
        reportErrors();
    }
    for (unsigned int i = 0; i < schemas->schema_cnt(); i++) {
        auto schema = schemas->schema(i);
        res.emplace_back(schema);
    }
    return res;
}

std::shared_ptr<Schema> SysrepoAccess::schema()
{
    return m_schema;
}

[[noreturn]] void SysrepoAccess::reportErrors() const
{
    // I only use get_last_errors to get error info, since the error code from
    // sysrepo_exception doesn't really give any meaningful information. For
    // example an "invalid argument" error could mean a node isn't enabled, or
    // it could mean something totally different and there is no documentation
    // for that, so it's better to just use the message sysrepo gives me.
    auto srErrors = m_session->get_last_errors();
    std::vector<DatastoreError> res;

    for (size_t i = 0; i < srErrors->error_cnt(); i++) {
        auto error = srErrors->error(i);
        res.emplace_back(error->message(), error->xpath() ? std::optional<std::string>{error->xpath()} : std::nullopt);
    }

    throw DatastoreException(res);
}

std::vector<ListInstance> SysrepoAccess::listInstances(const std::string& path)
{
    std::vector<ListInstance> res;
    auto lists = getItems(path);

    decltype(lists) instances;
    auto wantedTree = *(m_schema->dataNodeFromPath(path)->find_path(path.c_str())->data().begin());
    std::copy_if(lists.begin(), lists.end(), std::inserter(instances, instances.end()), [this, pathToCheck=wantedTree->schema()->path()](const auto& item) {
        // This filters out non-instances.
        if (item.second.type() != typeid(special_) || boost::get<special_>(item.second).m_value != SpecialValue::List) {
            return false;
        }

        // Now, getItems is recursive: it gives everything including nested lists. So I try create a tree from the instance...
        auto instanceTree = *(m_schema->dataNodeFromPath(item.first)->find_path(item.first.c_str())->data().begin());
        // And then check if its schema path matches the list we actually want. This filters out lists which are not the ones I requested.
        return instanceTree->schema()->path() == pathToCheck;
    });

    // If there are no instances, then just return
    if (instances.empty()) {
        return res;
    }

    // I need to find out which keys does the list have. To do that, I create a
    // tree from the first instance. This is gives me some top level node,
    // which will be our list in case out list is a top-level node. In case it
    // isn't, we have call find_path on the top level node. After that, I just
    // retrieve the keys.
    auto topLevelTree = m_schema->dataNodeFromPath(instances.begin()->first);
    auto list = *(topLevelTree->find_path(path.c_str())->data().begin());
    auto keys = libyang::Schema_Node_List{list->schema()}.keys();

    // Creating a full tree at the same time from the values sysrepo gives me
    // would be a pain (and after sysrepo switches to libyang meaningless), so
    // I just use this algorithm to create data nodes one by one and get the
    // key values from them.
    for (const auto& instance : instances) {
        auto wantedList = *(m_schema->dataNodeFromPath(instance.first)->find_path(path.c_str())->data().begin());
        ListInstance instanceRes;
        for (const auto& key : keys) {
            auto vec = wantedList->find_path(key->name())->data();
            auto leaf = libyang::Data_Node_Leaf_List{*(vec.begin())};
            instanceRes.emplace(key->name(), leafValueFromValue(leaf.value(), leaf.leaf_type()->base()));
        }
        res.emplace_back(instanceRes);
    }

    return res;
}

std::string SysrepoAccess::dump(const DataFormat format) const
{
    std::shared_ptr<libyang::Data_Node> root;
    auto input = getItems("/");
    if (input.empty()) {
        return "";
    }
    for (const auto& [k, v] : input) {
        if (v.type() == typeid(special_) && boost::get<special_>(v).m_value != SpecialValue::PresenceContainer) {
            continue;
        }
        if (!root) {
            root = m_schema->dataNodeFromPath(k, leafDataToString(v));
        } else {
            // Using UPDATE here, because in multi-key list, all of the keys get created with the first key (because they are encoded in the path)
            // and libyang complains if the node already exists.
            root->new_path(nullptr, k.c_str(), leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
        }
    }
    return root->print_mem(format == DataFormat::Xml ? LYD_XML : LYD_JSON, LYP_WITHSIBLINGS | LYP_FORMAT);
}
