#include "cypress_node.h"
#include "cypress.h"

namespace NRTYT {

TMapNode& TCypressNode::GetMap() {
    return const_cast<TMapNode&>(std::as_const(*this).GetMap());
}

const TMapNode& TCypressNode::GetMap() const {
    return std::visit(TOverloaded{
        [](const TMapNode& node) -> const TMapNode& { return node; },
        [](const TMountNode& node) -> const TMapNode& { return node->Root->GetMap(); },
        [&](const auto&) -> const TMapNode& {
            ythrow yexception() << "node " << Name << " can't be presented as map node";
        }
    }, Value);
}

bool TCypressNode::HasChild(const TString& name) const {
    auto childPos = GetMap().find(name);
    return childPos != GetMap().end();
}
NYT::TNodeId TCypressNode::GetChild(const TString& name) const {
    auto childPos = GetMap().find(name);
    if (childPos != GetMap().end()) {
        return childPos->second;
    } else {
        ythrow yexception() << "There is no child with name " << name << " in node " << Name;
    }
}
void TCypressNode::AddChild(TCypressNodePtr node) {
    GetMap()[node->GetName()] = node->GetId();
    node->SetParent(this);
}

void TCypressNode::RemoveChild(const TString& name) {
    GetMap().erase(name);
}

TVector<NYT::TNodeId> TCypressNode::ListChildren() const {
    TVector<NYT::TNodeId> result;
    for (const auto& item : GetMap()) {
        result.push_back(item.second);
    }
    return result;
}

void TCypressNode::ClearData() {
    if (GetType() == ENodeType::NT_TABLE) {
        std::get<TTableNode>(Value).Clear();
    }
}

const TTableNode& TCypressNode::AsTable() const {
    if (GetType() == ENodeType::NT_TABLE) {
        return std::get<TTableNode>(Value);
    }
    ythrow yexception() << "Node " << Name << " is not a table!";
}

TTableNode& TCypressNode::AsTable() {
    if (GetType() == ENodeType::NT_TABLE) {
        return std::get<TTableNode>(Value);
    }
    ythrow yexception() << "Node " << Name << " is not a table!";
}

bool TCypressNode::IsMountPoint() const {
    return std::holds_alternative<TMountNode>(Value);
}

const TCypressClient* TCypressNode::AsMountedClient() const {
    Y_ENSURE(std::holds_alternative<TMountNode>(Value), "Node " << Name << " is not a mount point");
    return std::get<TMountNode>(Value);
}

TCypressClient* TCypressNode::AsMountedClient() {
    Y_ENSURE(std::holds_alternative<TMountNode>(Value), "Node " << Name << " is not a mount point");
    return std::get<TMountNode>(Value);
}

} // namespace NRTYT
