#include "tree_finder.h"

using std::string, std::string_view;

void SearchTreeNode::insert(string_view partial_word,
                            const string *original_word) {
  if (partial_word.empty()) {
    words_.push_back(original_word);
  } else {
    children_[partial_word.front()].insert(
        string_view(partial_word).substr(1, partial_word.length()),
        original_word);
  }
}

const SearchTreeNode *SearchTreeNode::find(string_view search_term) const {
  if (search_term.empty()) {
    return this;
  }

  auto child = children_.find(search_term.front());
  if (child != children_.cend()) {
    return child->second.find(search_term.substr(1, search_term.length()));
  }

  return nullptr;
}

WordRefList SearchTreeNode::words() const {
  WordRefList results(words_);
  for (const auto &child : children_) {
    auto child_words = child.second.words();
    std::move(child_words.begin(), child_words.end(),
              std::back_inserter(results));
  }

  return results;
};

SearchTree::SearchTree(const WordList &word_list) {
  for (const auto &word : word_list) {
    insert(string_view(word), &word);
  }
}

TreeFinder::TreeFinder(const WordList &word_list) : search_tree_(word_list) {}

WordRefList TreeFinder::find_prefix(string_view search_term) const {
  const auto *result_node = search_tree_.find(search_term);
  if (result_node == nullptr) {
    return {};
  }

  return result_node->words();
}
