#ifndef CONTEXT_SWITCHER_CONTEXT_SWITCHER_H_
#define CONTEXT_SWITCHER_CONTEXT_SWITCHER_H_

#include <utility>
#include <cstdio>
#include <cstdint>
#include <new>

#include "assembly_bindings.h"
#include "continuation.h"
#include "lambda_capture.h"

namespace context_switcher {

template<typename F>
continuation enter_context(assembly_bindings::stack_pointer_t stack_memory, size_t stack_size, F &&lambda) {
  assembly_bindings::stack_pointer_t lambda_memory = stack_memory + stack_size - sizeof(lambda_capture<F>);
  auto *captured_lambda = place_lambda_capture(std::forward<F>(lambda), lambda_memory);

  assembly_bindings::stack_pointer_t stack_base = lambda_memory;
  assembly_bindings::stack_pointer_t stack_limit = stack_memory;

  assembly_bindings::callback_t callback = lambda_capture_callback<lambda_capture<F>>;
  return continuation{assembly_bindings::__cs_enter_context(stack_base, captured_lambda, callback, stack_limit)};
}

continuation switch_context(continuation &&cont);

}

#endif //CONTEXT_SWITCHER_CONTEXT_SWITCHER_H_
