#include <boost/algorithm/string/predicate.hpp>
#include <cmath>
#include "datastore_access.hpp"
#include "libyang_utils.hpp"
#include "utils.hpp"

leaf_data_ leafValueFromNode(libyang::S_Data_Node_Leaf_List node)
{
    std::function<leaf_data_(libyang::S_Data_Node_Leaf_List)> impl = [&impl](libyang::S_Data_Node_Leaf_List node) -> leaf_data_ {
        // value_type() is what's ACTUALLY stored inside `node`
        // Leafrefs sometimes don't hold a reference to another, but they have the actual pointed-to value.
        switch (node->value_type()) {
        case LY_TYPE_ENUM:
            return enum_{node->value()->enm()->name()};
        case LY_TYPE_UINT8:
            return node->value()->uint8();
        case LY_TYPE_UINT16:
            return node->value()->uint16();
        case LY_TYPE_UINT32:
            return node->value()->uint32();
        case LY_TYPE_UINT64:
            return node->value()->uint64();
        case LY_TYPE_INT8:
            return node->value()->int8();
        case LY_TYPE_INT16:
            return node->value()->int16();
        case LY_TYPE_INT32:
            return node->value()->int32();
        case LY_TYPE_INT64:
            return node->value()->int64();
        case LY_TYPE_DEC64: {
            auto v = node->value()->dec64();
            return v.value * std::pow(10, -v.digits);
        }
        case LY_TYPE_BOOL:
            return node->value()->bln();
        case LY_TYPE_STRING:
            return std::string{node->value()->string()};
        case LY_TYPE_BINARY:
            return binary_{node->value()->binary()};
        case LY_TYPE_IDENT:
            return identityRef_{node->value()->ident()->module()->name(), node->value()->ident()->name()};
        case LY_TYPE_EMPTY:
            return empty_{};
        case LY_TYPE_LEAFREF: {
            auto refsTo = node->value()->leafref();
            assert(refsTo);
            return impl(std::make_shared<libyang::Data_Node_Leaf_List>(node->value()->leafref()));
        }
        case LY_TYPE_BITS: {
            auto bits = node->value()->bit();
            std::vector<libyang::S_Type_Bit> filterNull;
            std::copy_if(bits.begin(), bits.end(), std::back_inserter(filterNull), [](auto bit) { return bit; });
            bits_ res;
            std::transform(filterNull.begin(), filterNull.end(), std::inserter(res.m_bits, res.m_bits.end()), [](const auto& bit) { return bit->name(); });
            return bits_{res};
        }
        default:
            return std::string{"(can't print)"};
        }
    };
    return impl(node);
}

namespace {
void impl_lyNodesToTree(DatastoreAccess::Tree& res, const std::vector<std::shared_ptr<libyang::Data_Node>> items, std::optional<std::string> ignoredXPathPrefix)
{
    auto stripXPathPrefix = [&ignoredXPathPrefix](auto path) {
        return ignoredXPathPrefix && path.find(*ignoredXPathPrefix) != std::string::npos ? path.substr(ignoredXPathPrefix->size()) : path;
    };

    for (const auto& it : items) {
        if (it->schema()->nodetype() == LYS_CONTAINER) {
            if (libyang::Schema_Node_Container{it->schema()}.presence()) {
                // The fact that the container is included in the data tree
                // means that it is present and I don't need to check any
                // value.
                res.emplace_back(stripXPathPrefix(it->path()), special_{SpecialValue::PresenceContainer});
            }
        }
        if (it->schema()->nodetype() == LYS_LIST) {
            res.emplace_back(stripXPathPrefix(it->path()), special_{SpecialValue::List});
        }
        if (it->schema()->nodetype() == LYS_LEAF || it->schema()->nodetype() == LYS_LEAFLIST) {
            auto leaf = std::make_shared<libyang::Data_Node_Leaf_List>(it);
            auto value = leafValueFromNode(leaf);
            res.emplace_back(stripXPathPrefix(it->path()), value);
        }
    }
}
}

void lyNodesToTree(DatastoreAccess::Tree& res, const std::vector<std::shared_ptr<libyang::Data_Node>> items, std::optional<std::string> ignoredXPathPrefix)
{
    for (auto it = items.begin(); it < items.end(); it++) {
        if ((*it)->schema()->nodetype() == LYS_LEAFLIST) {
            auto leafListPath = stripLeafListValueFromPath((*it)->path());
            res.emplace_back(leafListPath, special_{SpecialValue::LeafList});
            while (it != items.end() && boost::starts_with((*it)->path(), leafListPath)) {
                impl_lyNodesToTree(res, (*it)->tree_dfs(), ignoredXPathPrefix);
                it++;
            }
        } else {
            impl_lyNodesToTree(res, (*it)->tree_dfs(), ignoredXPathPrefix);
        }
    }
}

DatastoreAccess::Tree rpcOutputToTree(const std::string& rpcPath, libyang::S_Data_Node output)
{
    DatastoreAccess::Tree res;
    if (output) {
        // The output is "some top-level node". If we actually want the output of our RPC/action we need to use
        // find_path.  Also, our `path` is fully prefixed, but the output paths aren't. So we use outputNode->path() to
        // get the unprefixed path.

        auto outputNode = output->find_path(rpcPath.c_str())->data().front();
        lyNodesToTree(res, {outputNode}, joinPaths(outputNode->path(), "/"));
    }
    return res;
}

libyang::S_Data_Node treeToRpcInput(libyang::S_Context ctx, const std::string& path, DatastoreAccess::Tree in)
{
    auto root = std::make_shared<libyang::Data_Node>(ctx, path.c_str(), nullptr, LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
    for (const auto& [k, v] : in) {
        root->new_path(ctx, k.c_str(), leafDataToString(v).c_str(), LYD_ANYDATA_CONSTSTRING, LYD_PATH_OPT_UPDATE);
    }

    return root;
}
