/*
 * 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 <boost/algorithm/string/predicate.hpp>
#include "static_schema.hpp"
#include "utils.hpp"

StaticSchema::StaticSchema()
{
    m_nodes.emplace("/", std::unordered_map<std::string, NodeInfo>());
}

const std::unordered_map<std::string, NodeInfo>& StaticSchema::children(const std::string& name) const
{
    return m_nodes.at(name);
}

bool StaticSchema::isModule(const std::string& name) const
{
    return m_modules.find(name) != m_modules.end();
}

void StaticSchema::addContainer(const std::string& location, const std::string& name, yang::ContainerTraits isPresence)
{
    m_nodes.at(location).emplace(name, NodeInfo{yang::container{isPresence}, yang::AccessType::Writable});

    //create a new set of children for the new node
    std::string key = joinPaths(location, name);
    m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
}

bool StaticSchema::listHasKey(const schemaPath_& listPath, const std::string& key) const
{
    return listKeys(listPath).count(key);
}

std::string lastNodeOfSchemaPath(const std::string& path)
{
    std::string res = path;
    if (auto pos = res.find_last_of('/'); pos != res.npos) {
        res.erase(0, pos + 1);
    }
    return res;
}

const std::set<std::string> StaticSchema::listKeys(const schemaPath_& listPath) const
{
    auto listPathString = pathToSchemaString(listPath, Prefixes::Always);
    const auto& child = children(stripLastNodeFromPath(listPathString)).at(lastNodeOfSchemaPath(listPathString));
    const auto& list = std::get<yang::list>(child.m_nodeType);
    return list.m_keys;
}

void StaticSchema::addList(const std::string& location, const std::string& name, const std::set<std::string>& keys)
{
    m_nodes.at(location).emplace(name, NodeInfo{yang::list{keys}, yang::AccessType::Writable});

    std::string key = joinPaths(location, name);
    m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
}

std::set<identityRef_> StaticSchema::validIdentities(std::string_view module, std::string_view value)
{
    std::set<identityRef_> identities;
    getIdentSet(identityRef_{std::string{module}, std::string{value}}, identities);

    return identities;
}

void StaticSchema::addLeaf(const std::string& location, const std::string& name, const yang::LeafDataType& type, const yang::AccessType accessType)
{
    m_nodes.at(location).emplace(name, NodeInfo{yang::leaf{yang::TypeInfo{type, std::nullopt}}, accessType});
    std::string key = joinPaths(location, name);
    m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
}

void StaticSchema::addLeafList(const std::string& location, const std::string& name, const yang::LeafDataType& type)
{
    m_nodes.at(location).emplace(name, NodeInfo{yang::leaflist{yang::TypeInfo{type, std::nullopt}}, yang::AccessType::Writable});
    std::string key = joinPaths(location, name);
    m_nodes.emplace(key, std::unordered_map<std::string, NodeInfo>());
}

void StaticSchema::addModule(const std::string& name)
{
    m_modules.emplace(name);
}

void StaticSchema::addIdentity(const std::optional<identityRef_>& base, const identityRef_& name)
{
    if (base) {
        m_identities.at(base.value()).emplace(name);
    }

    m_identities.emplace(name, std::set<identityRef_>());
}

void StaticSchema::getIdentSet(const identityRef_& ident, std::set<identityRef_>& res) const
{
    res.insert(ident);
    auto derivedIdentities = m_identities.at(ident);
    for (auto it : derivedIdentities) {
        getIdentSet(it, res);
    }
}

yang::TypeInfo StaticSchema::leafType(const schemaPath_& location, const ModuleNodePair& node) const
{
    std::string locationString = pathToSchemaString(location, Prefixes::Always);
    auto nodeType = children(locationString).at(fullNodeName(location, node)).m_nodeType;
    if (std::holds_alternative<yang::leaf>(nodeType)) {
        return std::get<yang::leaf>(nodeType).m_type;
    }

    if (std::holds_alternative<yang::leaflist>(nodeType)) {
        return std::get<yang::leaflist>(nodeType).m_type;
    }

    throw std::logic_error("StaticSchema::leafType: Path is not a leaf or a leaflist");
}

yang::TypeInfo StaticSchema::leafType(const std::string& path) const
{
    auto locationString = stripLastNodeFromPath(path);
    auto node = lastNodeOfSchemaPath(path);
    return std::get<yang::leaf>(children(locationString).at(node).m_nodeType).m_type;
}

std::set<ModuleNodePair> StaticSchema::availableNodes(const boost::variant<dataPath_, schemaPath_, module_>& path, const Recursion recursion) const
{
    if (recursion == Recursion::Recursive) {
        throw std::logic_error("Recursive StaticSchema::availableNodes is not implemented. It shouldn't be used in tests.");
    }

    std::set<ModuleNodePair> res;
    if (path.type() == typeid(module_)) {
        auto topLevelNodes = m_nodes.at("");
        auto modulePlusColon = boost::get<module_>(path).m_name + ":";
        for (const auto& it : topLevelNodes) {
            if (boost::algorithm::starts_with(it.first, modulePlusColon)) {
                res.insert(splitModuleNode(it.first));
            }
        }
        return res;
    }

    auto getTopLevelModule = [] (const auto& path) -> boost::optional<std::string> {
        if (!path.m_nodes.empty()) {
            return path.m_nodes.begin()->m_prefix.flat_map([] (const auto& module) {return boost::optional<std::string>(module.m_name);});
        }

        return boost::none;
    };

    std::string locationString;
    boost::optional<std::string> topLevelModule;
    if (path.type() == typeid(schemaPath_)) {
        locationString = pathToSchemaString(boost::get<schemaPath_>(path), Prefixes::Always);
        topLevelModule = getTopLevelModule(boost::get<schemaPath_>(path));
    } else {
        locationString = pathToSchemaString(boost::get<dataPath_>(path), Prefixes::Always);
        topLevelModule = getTopLevelModule(boost::get<dataPath_>(path));
    }

    auto childrenRef = children(locationString);

    std::transform(childrenRef.begin(), childrenRef.end(), std::inserter(res, res.end()), [path, topLevelModule](const auto& it) {
        auto res = splitModuleNode(it.first);
        if (topLevelModule == res.first) {
            res.first = boost::none;
        }
        return res;
    });
    return res;
}

struct impl_nodeType {

    yang::NodeTypes operator()(const yang::container& cont)
    {
        if (cont.m_presence == yang::ContainerTraits::Presence) {
            return yang::NodeTypes::PresenceContainer;
        }
        return yang::NodeTypes::Container;
    }
    yang::NodeTypes operator()(const yang::list&)
    {
        return yang::NodeTypes::List;
    }
    yang::NodeTypes operator()(const yang::leaf&)
    {
        return yang::NodeTypes::Leaf;

    }
    yang::NodeTypes operator()(const yang::leaflist&)
    {
        return yang::NodeTypes::LeafList;
    }
};

yang::NodeTypes StaticSchema::nodeType(const schemaPath_& location, const ModuleNodePair& node) const
{
    std::string locationString = pathToSchemaString(location, Prefixes::Always);
    auto fullName = fullNodeName(location, node);
    try {
        auto targetNode = children(locationString).at(fullName);

        return std::visit(impl_nodeType{}, targetNode.m_nodeType);
    } catch (std::out_of_range&) {
        throw InvalidNodeException();
    }
}

std::string fullNodeName(const std::string& location, const std::string& node)
{
    // If the node already contains a module name, just return it.
    if (node.find_first_of(':') != std::string::npos) {
        return node;
    }

    // Otherwise take the module name from the first node of location.
    return location.substr(location.find_first_not_of('/'), location.find_first_of(':') - 1) + ":" + node;
}

bool StaticSchema::isConfig(const std::string& leafPath) const
{
    auto locationString = stripLastNodeFromPath(leafPath);

    auto node = fullNodeName(locationString, lastNodeOfSchemaPath(leafPath));
    return children(locationString).at(node).m_configType == yang::AccessType::Writable;
}

std::optional<std::string> StaticSchema::description([[maybe_unused]] const std::string& path) const
{
    throw std::runtime_error{"StaticSchema::description not implemented"};
}

yang::Status StaticSchema::status([[maybe_unused]] const std::string& location) const
{
    throw std::runtime_error{"Internal error: StaticSchema::status(std::string) not implemented. The tests should not have called this overload."};
}

yang::NodeTypes StaticSchema::nodeType(const std::string& path) const
{
    auto locationString = stripLastNodeFromPath(path);

    auto node = fullNodeName(locationString, lastNodeOfSchemaPath(path));
    return std::visit(impl_nodeType{}, children(locationString).at(node).m_nodeType);
}

std::string StaticSchema::leafrefPath([[maybe_unused]] const std::string& leafrefPath) const
{
    throw std::runtime_error{"Internal error: StaticSchema::leafrefPath(std::string) not implemented. The tests should not have called this overload."};
}

bool StaticSchema::leafIsKey([[maybe_unused]] const std::string& leafPath) const
{
    throw std::runtime_error{"Internal error: StaticSchema::leafIsKey(std::string) not implemented. The tests should not have called this overload."};
}

std::optional<std::string> StaticSchema::leafTypeName([[maybe_unused]] const std::string& path) const
{
    throw std::runtime_error{"Internal error: StaticSchema::leafTypeName(std::string) not implemented. The tests should not have called this overload."};
}

std::optional<std::string> StaticSchema::defaultValue([[maybe_unused]] const std::string& leafPath) const
{
    throw std::runtime_error{"Internal error: StaticSchema::defaultValue(std::string) not implemented. The tests should not have called this overload."};
}
