// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

#include "Views/ShadowNodeRegistry.h"
#include "Views/PaperShadowNode.h"
#include "Views/ViewManager.h"

#include <glog/logging.h>

namespace Microsoft::ReactNative {

void ShadowNodeDeleter::operator()(ShadowNode *node) {
  if (node->m_viewManager)
    node->m_viewManager->destroyShadow(node);
}

void ShadowNodeRegistry::addRootView(std::unique_ptr<ShadowNode, ShadowNodeDeleter> &&root, int64_t rootViewTag) {
  m_roots.insert(rootViewTag);
  m_allNodes[rootViewTag] = std::move(root);
}

ShadowNode &ShadowNodeRegistry::getRoot(int64_t rootViewTag) {
  CHECK(m_roots.find(rootViewTag) != m_roots.end());
  return getNode(rootViewTag);
}

void ShadowNodeRegistry::removeRootView(int64_t rootViewTag) {
  m_roots.erase(rootViewTag);
  removeNode(rootViewTag);
}

void ShadowNodeRegistry::addNode(std::unique_ptr<ShadowNode, ShadowNodeDeleter> &&node, int64_t tag) {
  m_allNodes[tag] = std::move(node);
}

ShadowNode *ShadowNodeRegistry::findNode(int64_t tag) {
  auto iter = m_allNodes.find(tag);
  return (iter != m_allNodes.end()) ? iter->second.get() : nullptr;
}

ShadowNode &ShadowNodeRegistry::getNode(int64_t tag) {
  return *m_allNodes.at(tag);
}

void ShadowNodeRegistry::removeNode(int64_t tag) {
  m_allNodes.erase(tag);
}

void ShadowNodeRegistry::removeAllRootViews(const std::function<void(int64_t rootViewTag)> &fn) {
  while (!m_roots.empty())
    fn(*m_roots.begin());
}

std::unordered_set<int64_t> &ShadowNodeRegistry::getAllRoots() {
  return m_roots;
}

void ShadowNodeRegistry::ForAllNodes(const Mso::FunctorRef<void(int64_t, shadow_ptr const &) noexcept> &fnDo) noexcept {
  for (auto &kvp : m_allNodes) {
    fnDo(kvp.first, kvp.second);
  }
}

} // namespace Microsoft::ReactNative
