#ifndef MODULE_REGISTRY_HPP
#define MODULE_REGISTRY_HPP

#include <language/modules/IModule.hpp>

#include <map>
#include <memory>
#include <string>

class ASTNode;
class ASTNodeDataType;
class SymbolTable;

class ModuleRepository
{
 private:
  std::map<std::string, std::unique_ptr<IModule>> m_module_set;

  void _subscribe(std::unique_ptr<IModule> a);

  template <typename NameEmbedderMapT, typename EmbedderTableT>
  void _populateEmbedderTableT(const ASTNode& module_node,
                               const std::string& module_name,
                               const NameEmbedderMapT& name_embedder_map,
                               const ASTNodeDataType& data_type,
                               SymbolTable& symbol_table,
                               EmbedderTableT& embedder_table);

 public:
  void populateSymbolTable(const ASTNode& module_name_node, SymbolTable& symbol_table);
  void populateMandatorySymbolTable(const ASTNode& root_node, SymbolTable& symbol_table);

  std::string getAvailableModules() const;
  std::string getModuleInfo(const std::string& module_name) const;

  const ModuleRepository& operator=(const ModuleRepository&) = delete;
  const ModuleRepository& operator=(ModuleRepository&&) = delete;

  ModuleRepository(const ModuleRepository&) = delete;
  ModuleRepository(ModuleRepository&&)      = delete;

  ModuleRepository();
  ~ModuleRepository() = default;
};

#endif   // MODULE_REGISTRY_HPP