/*
 * 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 "parser_context.hpp"
ParserContext::ParserContext(const Schema& schema, const std::shared_ptr<const DataQuery> dataQuery, const dataPath_& curDir)
    : m_schema(schema)
    , m_curPathOrig(curDir)
    , m_dataquery(dataQuery)
    , m_curPath(curDir)
{
    if (!currentDataPath().m_nodes.empty() && currentDataPath().m_nodes.at(0).m_prefix)
        m_topLevelModulePresent = true;
}

void ParserContext::clearPath()
{
    m_curPath = dataPath_{Scope::Absolute, {}};
    m_topLevelModulePresent = false;
}

schemaPath_ ParserContext::currentSchemaPath()
{
    if (m_curPath.type() == typeid(dataPath_)) {
        return dataPathToSchemaPath(boost::get<dataPath_>(m_curPath));
    } else {
        return boost::get<schemaPath_>(m_curPath);
    }
}

dataPath_ ParserContext::currentDataPath()
{
    if (m_curPath.type() != typeid(dataPath_)) {
        throw std::runtime_error("Tried getting a dataPath_ from ParserContext when only schemaPath_ was available.");
    }
    return boost::get<dataPath_>(m_curPath);
}

void ParserContext::pushPathFragment(const dataNode_& node)
{
    auto pushNode = [this] (auto& where, const auto& what) {
        if (std::holds_alternative<nodeup_>(what.m_suffix)) {
            where.m_nodes.pop_back();
            if (where.m_nodes.empty()) {
                m_topLevelModulePresent = false;
            }
        } else {
            where.m_nodes.push_back(what);
        }
    };

    if (m_curPath.type() == typeid(dataPath_)) {
        pushNode(boost::get<dataPath_>(m_curPath), node);
    } else {
        pushNode(boost::get<schemaPath_>(m_curPath), dataNodeToSchemaNode(node));
    }
}

void ParserContext::pushPathFragment(const schemaNode_& node)
{
    if (m_curPath.type() == typeid(dataPath_)) {
        m_curPath = dataPathToSchemaPath(boost::get<dataPath_>(m_curPath));
    }

    boost::get<schemaPath_>(m_curPath).m_nodes.push_back(node);
    if (currentSchemaPath().m_nodes.empty()) {
        m_topLevelModulePresent = false;
    }
}

void ParserContext::resetPath()
{
    m_curPath = m_curPathOrig;
    m_topLevelModulePresent = !currentDataPath().m_nodes.empty() && currentDataPath().m_nodes.at(0).m_prefix;
}
