#include "parallel_finder.h"

#include <mutex>
#include <thread>

using std::mutex, std::thread, std::vector, std::forward_list, std::string,
    std::string_view;

ParallelFinder::ParallelFinder(const WordList &word_list)
    : word_list_(word_list) {}

forward_list<const string *>
ParallelFinder::find_prefix(string_view search_prefix) const {
  forward_list<const string *> result;
  mutex result_mutex;

  const size_t word_list_size = word_list_.size();
  const size_t thread_count =
      std::min<size_t>(thread::hardware_concurrency(), word_list_size);

  vector<thread> search_threads;
  for (size_t thread_index = 0; thread_index < thread_count; ++thread_index) {
    const size_t first_index = thread_index * (word_list_size / thread_count);

    const size_t last_index =
        (thread_index == thread_count - 1)
            ? word_list_size
            : (thread_index + 1) * (word_list_size / thread_count);

    search_threads.emplace_back(
        WordList::find_prefix_in_range, cref(word_list_), cref(search_prefix),
        first_index, last_index, ref(result), ref(result_mutex));
  }

  for (auto &thread : search_threads) {
    thread.join();
  }

  return result;
}
