#include <catch.hpp>

#include <atomic>
#include <thread>
#include <mutex>

#include "pls/internal/scheduling/scheduler.h"
#include "pls/internal/scheduling/cont.h"
#include "pls/internal/scheduling/cont_manager.h"
#include "pls/internal/scheduling/scheduler_memory.h"
#include "pls/internal/scheduling/parallel_result.h"

using namespace pls::internal::scheduling;

// TODO: Introduce actual tests once multiple threads work...
TEST_CASE("continuation stealing", "[internal/scheduling/cont_manager.h]") {
  const int NUM_THREADS = 2;
  const int NUM_TASKS = 8;
  const int MAX_TASK_STACK_SIZE = 8;
  const int NUM_CONTS = 8;
  const int MAX_CONT_SIZE = 256;

  static_scheduler_memory<NUM_THREADS,
                          NUM_TASKS,
                          MAX_TASK_STACK_SIZE,
                          NUM_CONTS,
                          MAX_CONT_SIZE> static_scheduler_memory;

  scheduler scheduler{static_scheduler_memory, NUM_THREADS};

  // Coordinate progress to match OUR order
  std::atomic<int> progress{0};

  // Order:
  // 0) work on first task on main thread
  // 1) second thread stole right task

  scheduler.perform_work([&]() {
    return scheduler::par([&]() {
      while (progress.load() != 1);
      return parallel_result<int>{0};
    }, [&]() {
      progress.store(1);
      return parallel_result<int>{0};
    }).then([&](int, int) {

      return parallel_result<int>{0};
    });
  });
}
