/*
 * 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 <libyang-cpp/Enum.hpp>
#include <libyang-cpp/Utils.hpp>
#include <string_view>
#include "UniqueResource.hpp"
#include "utils.hpp"
#include "yang_schema.hpp"

class YangLoadError : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
    ~YangLoadError() override = default;
};

class UnsupportedYangTypeException : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
    ~UnsupportedYangTypeException() override = default;
};

class InvalidSchemaQueryException : public std::runtime_error {
public:
    using std::runtime_error::runtime_error;
    ~InvalidSchemaQueryException() override = default;
};

YangSchema::YangSchema()
    : m_context(std::nullopt, libyang::ContextOptions::DisableSearchDirs | libyang::ContextOptions::SetPrivParsed)
{
}

YangSchema::YangSchema(libyang::Context lyCtx)
    : m_context(lyCtx)
{
}

YangSchema::~YangSchema() = default;

void YangSchema::addSchemaString(const char* schema)
{
    m_context.parseModule(std::string{schema}, libyang::SchemaFormat::YANG);
}

void YangSchema::addSchemaDirectory(const char* directoryName)
{
    m_context.setSearchDir(directoryName);
}

void YangSchema::addSchemaFile(const char* filename)
{
    m_context.parseModule(std::filesystem::path{filename}, libyang::SchemaFormat::YANG);
}

bool YangSchema::isModule(const std::string& name) const
{
    return m_context.getModuleImplemented(name).has_value();
}

bool YangSchema::listHasKey(const schemaPath_& listPath, const std::string& key) const
{
    const auto keys = listKeys(listPath);
    return keys.find(key) != keys.end();
}

bool YangSchema::leafIsKey(const std::string& leafPath) const
{
    auto node = getSchemaNode(leafPath);
    if (!node || node->nodeType() != libyang::NodeType::Leaf) {
        return false;
    }

    return node->asLeaf().isKey();
}

std::optional<libyang::SchemaNode> YangSchema::impl_getSchemaNode(const std::string& node) const
{
    // libyang::Context::findPath throws an exception, when no matching schema node is found. This exception has the
    // ValidationFailure error code. We will catch that exception (and rethrow if it's not the correct error code.
    //
    // Also, we need to use findPath twice if we're trying to find output nodes.
    try {
        return m_context.findPath(node);
    } catch (libyang::ErrorWithCode& err) {
        if (err.code() != libyang::ErrorCode::ValidationFailure) {
            throw;
        }
    }
    try {
        return m_context.findPath(node, libyang::InputOutputNodes::Output);
    } catch (libyang::ErrorWithCode& err) {
        if (err.code() != libyang::ErrorCode::ValidationFailure) {
            throw;
        }
    }

    // We didn't find a matching node.
    return std::nullopt;
}


std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const std::string& node) const
{
    return impl_getSchemaNode(node);
}

std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const schemaPath_& location, const ModuleNodePair& node) const
{
    std::string absPath = joinPaths(pathToSchemaString(location, Prefixes::Always), fullNodeName(location, node));

    return impl_getSchemaNode(absPath);
}

std::optional<libyang::SchemaNode> YangSchema::getSchemaNode(const schemaPath_& listPath) const
{
    std::string absPath = pathToSchemaString(listPath, Prefixes::Always);
    return impl_getSchemaNode(absPath);
}

const std::set<std::string> YangSchema::listKeys(const schemaPath_& listPath) const
{
    auto node = getSchemaNode(listPath);
    if (node->nodeType() != libyang::NodeType::List) {
        return {};
    }

    std::set<std::string> keys;
    auto keysVec = node->asList().keys();

    std::transform(keysVec.begin(), keysVec.end(), std::inserter(keys, keys.begin()), [](const auto& it) { return std::string{it.name()}; });
    return keys;
}

std::set<enum_> enumValues(const libyang::types::Type& type)
{
    auto enums = type.asEnum().items();
    std::set<enum_> enumSet;
    std::transform(enums.begin(), enums.end(), std::inserter(enumSet, enumSet.end()), [](auto it) { return enum_{std::string{it.name}}; });
    return enumSet;
}

std::set<identityRef_> validIdentities(const libyang::types::Type& type)
{
    std::set<identityRef_> identSet;

    std::function<void(const std::vector<libyang::Identity>&)> impl = [&identSet, &impl] (const std::vector<libyang::Identity>& idents) {
        if (idents.empty()) {
            return;
        }

        for (const auto& ident : idents) {
            identSet.emplace(std::string{ident.module().name()}, std::string{ident.name()});
            impl(ident.derived());
        }
    };

    for (const auto& base : type.asIdentityRef().bases()) {
        impl(base.derived());
    }

    return identSet;
}

std::string leafrefPath(const libyang::types::Type& type)
{
    return std::string{type.asLeafRef().path()};
}

template <typename NodeType>
yang::TypeInfo YangSchema::impl_leafType(const NodeType& node) const
{
    using namespace std::string_literals;
    auto leaf = std::make_shared<NodeType>(node);
    auto leafUnits = leaf->units();
    std::function<yang::TypeInfo(const libyang::types::Type&)> resolveType;
    resolveType = [&resolveType, leaf, leafUnits](const libyang::types::Type& type) -> yang::TypeInfo {
        yang::LeafDataType resType;
        switch (type.base()) {
        case libyang::LeafBaseType::String:
            resType.emplace<yang::String>();
            break;
        case libyang::LeafBaseType::Dec64:
            resType.emplace<yang::Decimal>();
            break;
        case libyang::LeafBaseType::Bool:
            resType.emplace<yang::Bool>();
            break;
        case libyang::LeafBaseType::Int8:
            resType.emplace<yang::Int8>();
            break;
        case libyang::LeafBaseType::Int16:
            resType.emplace<yang::Int16>();
            break;
        case libyang::LeafBaseType::Int32:
            resType.emplace<yang::Int32>();
            break;
        case libyang::LeafBaseType::Int64:
            resType.emplace<yang::Int64>();
            break;
        case libyang::LeafBaseType::Uint8:
            resType.emplace<yang::Uint8>();
            break;
        case libyang::LeafBaseType::Uint16:
            resType.emplace<yang::Uint16>();
            break;
        case libyang::LeafBaseType::Uint32:
            resType.emplace<yang::Uint32>();
            break;
        case libyang::LeafBaseType::Uint64:
            resType.emplace<yang::Uint64>();
            break;
        case libyang::LeafBaseType::Binary:
            resType.emplace<yang::Binary>();
            break;
        case libyang::LeafBaseType::Empty:
            resType.emplace<yang::Empty>();
            break;
        case libyang::LeafBaseType::Enum:
            resType.emplace<yang::Enum>(enumValues(type));
            break;
        case libyang::LeafBaseType::IdentityRef:
            resType.emplace<yang::IdentityRef>(validIdentities(type));
            break;
        case libyang::LeafBaseType::Leafref:
            resType.emplace<yang::LeafRef>(::leafrefPath(type), std::make_unique<yang::TypeInfo>(resolveType(type.asLeafRef().resolvedType())));
            break;
        case libyang::LeafBaseType::Bits: {
            auto resBits = yang::Bits{};
            for (const auto& bit : type.asBits().items()) {
                resBits.m_allowedValues.emplace(std::string{bit.name});
            }
            resType.emplace<yang::Bits>(std::move(resBits));
            break;
        }
        case libyang::LeafBaseType::Union: {
            auto resUnion = yang::Union{};
            for (auto unionType : type.asUnion().types()) {
                resUnion.m_unionTypes.emplace_back(resolveType(unionType));
            }
            resType.emplace<yang::Union>(std::move(resUnion));
            break;
        }
        case libyang::LeafBaseType::InstanceIdentifier: {
            resType.emplace<yang::InstanceIdentifier>();
            break;
        }
        default:
            using namespace std::string_literals;
            throw UnsupportedYangTypeException("the type of "s +
                    std::string{leaf->name()} +
                    " is not supported: " +
                    std::to_string(std::underlying_type_t<libyang::LeafBaseType>(leaf->valueType().base())));
        }
        // note https://gcc.gnu.org/bugzilla/show_bug.cgi?id=109434
        std::optional<std::string> typeDesc;

        try {
            typeDesc = type.description();
        } catch (libyang::ParsedInfoUnavailable&) {
            // libyang context doesn't have the parsed info.
        }

        return yang::TypeInfo(resType, std::optional<std::string>{leafUnits}, typeDesc);
    };
    return resolveType(leaf->valueType());
}

yang::TypeInfo YangSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
{
    auto lyNode = getSchemaNode(location, node);
    switch (lyNode->nodeType()) {
    case libyang::NodeType::Leaf:
        return impl_leafType(lyNode->asLeaf());
    case libyang::NodeType::Leaflist:
        return impl_leafType(lyNode->asLeafList());
    default:
        throw std::logic_error("YangSchema::leafType: type must be leaf or leaflist");
    }
}

yang::TypeInfo YangSchema::leafType(const std::string& path) const
{
    auto lyNode = getSchemaNode(path);
    switch (lyNode->nodeType()) {
    case libyang::NodeType::Leaf:
        return impl_leafType(lyNode->asLeaf());
    case libyang::NodeType::Leaflist:
        return impl_leafType(lyNode->asLeafList());
    default:
        throw std::logic_error("YangSchema::leafType: type must be leaf or leaflist");
    }
}

std::optional<std::string> YangSchema::leafTypeName(const std::string& path) const
{
    auto leaf = getSchemaNode(path)->asLeaf();
    try {
        return std::string{leaf.valueType().name()};
    } catch (libyang::ParsedInfoUnavailable&) {
        return std::nullopt;
    }
}

std::string YangSchema::leafrefPath(const std::string& leafrefPath) const
{
    using namespace std::string_literals;
    return ::leafrefPath(getSchemaNode(leafrefPath)->asLeaf().valueType());
}

std::set<std::string> YangSchema::modules() const
{
    const auto& modules = m_context.modules();

    std::set<std::string> res;
    std::transform(modules.begin(), modules.end(), std::inserter(res, res.end()), [](const auto module) { return std::string{module.name()}; });
    return res;
}

std::set<ModuleNodePair> YangSchema::availableNodes(const boost::variant<dataPath_, schemaPath_, module_>& path, const Recursion recursion) const
{
    using namespace std::string_view_literals;
    std::set<ModuleNodePair> res;
    std::vector<libyang::ChildInstanstiables> nodeCollections;
    std::string topLevelModule;

    if (path.type() == typeid(module_)) {
        nodeCollections.emplace_back(m_context.getModuleLatest(boost::get<module_>(path).m_name)->childInstantiables());
    } else {
        auto schemaPath = anyPathToSchemaPath(path);
        if (schemaPath.m_nodes.empty()) {
            for (const auto& module : m_context.modules()) {
                if (module.implemented()) {
                    nodeCollections.emplace_back(module.childInstantiables());
                }
            }
        } else {
            const auto pathString = pathToSchemaString(schemaPath, Prefixes::Always);
            const auto node = getSchemaNode(pathString);
            nodeCollections.emplace_back(node->childInstantiables());
            topLevelModule = schemaPath.m_nodes.begin()->m_prefix->m_name;
        }
    }

    for (const auto& coll : nodeCollections) {
        for (const auto& node : coll) {
            if (node.module().name() == "ietf-yang-library"sv) {
                continue;
            }

            if (node.module().name() == "ietf-yang-schema-mount"sv) {
                continue;
            }

            if (recursion == Recursion::Recursive) {
                for (auto it : node.childrenDfs()) {
                    res.insert(ModuleNodePair(boost::none, it.path()));
                }
            } else {
                ModuleNodePair toInsert;
                if (topLevelModule.empty() || topLevelModule != node.module().name()) {
                    toInsert.first = std::string{node.module().name()};
                }
                toInsert.second = node.name();
                res.insert(toInsert);
            }
        }
    }

    return res;
}

void YangSchema::loadModule(const std::string& moduleName)
{
    m_context.loadModule(moduleName);
}

void YangSchema::setEnabledFeatures(const std::string& moduleName, const std::vector<std::string>& features)
{
    using namespace std::string_literals;
    auto module = getYangModule(moduleName);
    if (!module) {
        throw std::runtime_error("Module \""s + moduleName + "\" doesn't exist.");
    }
    try {
        module->setImplemented(features);
    } catch (libyang::ErrorWithCode&) {
        throw std::runtime_error("Can't enable features for module \"" + moduleName + "\".");
    }
}

void YangSchema::registerModuleCallback(const std::function<std::string(const std::string_view, const std::optional<std::string_view>, const std::optional<std::string_view>, const std::optional<std::string_view>)>& clb)
{
    auto lambda = [clb](const auto mod_name, const auto mod_revision, const auto submod_name, const auto submod_revision) -> std::optional<libyang::ModuleInfo> {
        (void)submod_revision;
        auto moduleSource = clb(mod_name, mod_revision, submod_name, submod_revision);
        if (moduleSource.empty()) {
            return std::nullopt;
        }
        return libyang::ModuleInfo {
            .data = moduleSource,
            .format = libyang::SchemaFormat::YANG

        };
    };

    m_context.registerModuleCallback(lambda);
}

libyang::CreatedNodes YangSchema::dataNodeFromPath(const std::string& path, const std::optional<const std::string> value) const
{
    auto options = [this, &path, &value] {
        // If we're creating a node without a value and it's not the "empty" type, then we also need the Opaque flag.
        auto schema = getSchemaNode(path);
        if (schema->nodeType() == libyang::NodeType::Leaf &&
            schema->asLeaf().valueType().base() != libyang::LeafBaseType::Empty &&
            !value) {
            return std::optional<libyang::CreationOptions>{libyang::CreationOptions::Opaque};
        }

        return std::optional<libyang::CreationOptions>{};
    }();
    return m_context.newPath2(path, value, options);
}

std::optional<libyang::Module> YangSchema::getYangModule(const std::string& name)
{
    return m_context.getModuleImplemented(name);
}

namespace {
yang::NodeTypes impl_nodeType(const libyang::SchemaNode& node)
{
    switch (node.nodeType()) {
    case libyang::NodeType::Container:
        return node.asContainer().isPresence() ? yang::NodeTypes::PresenceContainer : yang::NodeTypes::Container;
    case libyang::NodeType::Leaf:
        return yang::NodeTypes::Leaf;
    case libyang::NodeType::List:
        return yang::NodeTypes::List;
    case libyang::NodeType::RPC:
        return yang::NodeTypes::Rpc;
    case libyang::NodeType::Action:
        return yang::NodeTypes::Action;
    case libyang::NodeType::Notification:
        return yang::NodeTypes::Notification;
    case libyang::NodeType::AnyXML:
        return yang::NodeTypes::AnyXml;
    case libyang::NodeType::Leaflist:
        return yang::NodeTypes::LeafList;
    default:
        throw InvalidNodeException(); // FIXME: Implement all types.
    }
}
}

yang::NodeTypes YangSchema::nodeType(const schemaPath_& location, const ModuleNodePair& node) const
{
    return impl_nodeType(*getSchemaNode(location, node));
}

yang::NodeTypes YangSchema::nodeType(const std::string& path) const
{
    return impl_nodeType(*getSchemaNode(path));
}

std::optional<std::string> YangSchema::description(const std::string& path) const
{
    auto desc = getSchemaNode(path.c_str())->description();
    return desc ? std::optional<std::string>{desc} : std::nullopt;

}

yang::Status YangSchema::status(const std::string& location) const
{
    auto node = getSchemaNode(location.c_str());
    switch (node->status()) {
    case libyang::Status::Deprecated:
        return yang::Status::Deprecated;
    case libyang::Status::Obsolete:
        return yang::Status::Obsolete;
    case libyang::Status::Current:
        return yang::Status::Current;
    }

    __builtin_unreachable();
}

bool YangSchema::hasInputNodes(const std::string& path) const
{
    auto node = getSchemaNode(path.c_str());
    if (auto type = node->nodeType(); type != libyang::NodeType::Action && type != libyang::NodeType::RPC) {
        throw std::logic_error("StaticSchema::hasInputNodes called with non-RPC/action path");
    }

    // The first child gives the /input node and then I check whether it has a child.
    return node->child()->child().has_value();
}

bool YangSchema::isConfig(const std::string& path) const
{
    auto node = getSchemaNode(path.c_str());
    if (node->isInput()) {
        return true;
    }

    try {
        if (node->config() == libyang::Config::True) {
            return true;
        }
    } catch (libyang::Error&) {
        // For non-data nodes (like `rpc`), the config value can't be retrieved. In this case, we'll just default to
        // "false".
    }

    return false;
}

std::optional<std::string> YangSchema::defaultValue(const std::string& leafPath) const
{
    return std::optional<std::string>{getSchemaNode(leafPath)->asLeaf().defaultValueStr()};
}

std::string YangSchema::dataPathToSchemaPath(const std::string& path)
{
    return std::string{getSchemaNode(path)->path()};
}
