#include <language/ast/ASTModulesImporter.hpp>

#include <language/PEGGrammar.hpp>
#include <language/utils/OperatorRepository.hpp>
#include <utils/ConsoleManager.hpp>

void
ASTModulesImporter::_importModule(ASTNode& import_node)
{
  Assert(import_node.is_type<language::import_instruction>());
  Assert(import_node.children[0]->is_type<language::module_name>());

  const ASTNode& module_name_node = *import_node.children[0];
  const std::string module_name   = module_name_node.string();

  if (auto [i_module_name, success] = m_imported_modules.insert(module_name); not success) {
    if (ConsoleManager::showPreamble()) {
      std::cout << " * ignoring  '" << rang::fgB::green << module_name << rang::style::reset
                << "' module, already imported\n";
    }
    return;
  }

  if (ConsoleManager::showPreamble()) {
    std::cout << " * importing '" << rang::fgB::green << module_name << rang::style::reset << "' module\n";
  }

  m_module_repository.populateSymbolTable(module_name_node, m_symbol_table);
  m_module_repository.registerOperators(module_name);
}

void
ASTModulesImporter::_importAllModules(ASTNode& node)
{
  if (node.is_type<language::import_instruction>()) {
    this->_importModule(node);
  } else {
    for (auto& child : node.children) {
      this->_importAllModules(*child);
    }
  }
}

ASTModulesImporter::ASTModulesImporter(ASTNode& root_node) : m_symbol_table{*root_node.m_symbol_table}
{
  Assert(root_node.is_root());
  OperatorRepository::instance().reset();
  m_module_repository.populateMandatorySymbolTable(root_node, m_symbol_table);

  this->_importAllModules(root_node);

  if (ConsoleManager::showPreamble()) {
    std::cout << " - loaded modules\n";
  }
}