// Copyright 2023 The Pigweed Authors
//
// Licensed under the Apache License, Version 2.0 (the "License"); you may not
// use this file except in compliance with the License. You may obtain a copy of
// the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
// License for the specific language governing permissions and limitations under
// the License.

#include "pw_async2/func_task.h"

#include <optional>
#include <utility>

#include "pw_async2/dispatcher_for_test.h"
#include "pw_function/function.h"
#include "pw_unit_test/framework.h"

namespace {

using ::pw::Function;
using ::pw::async2::Context;
using ::pw::async2::DispatcherForTest;
using ::pw::async2::FuncTask;
using ::pw::async2::Pending;
using ::pw::async2::Poll;
using ::pw::async2::Ready;
using ::pw::async2::RunOnceTask;
using ::pw::async2::Task;
using ::pw::async2::Waker;

TEST(FuncTask, PendDelegatesToFunc) {
  DispatcherForTest dispatcher;

  Waker waker;
  int poll_count = 0;
  bool allow_completion = false;

  FuncTask func_task([&](Context& cx) -> Poll<> {
    ++poll_count;
    if (allow_completion) {
      return Ready();
    }
    PW_ASYNC_STORE_WAKER(cx, waker, "func_task is waiting for waker");
    return Pending();
  });

  dispatcher.Post(func_task);

  EXPECT_EQ(poll_count, 0);
  EXPECT_TRUE(dispatcher.RunUntilStalled());
  EXPECT_EQ(poll_count, 1);

  // Unwoken task is not polled.
  EXPECT_TRUE(dispatcher.RunUntilStalled());
  EXPECT_EQ(poll_count, 1);

  waker.Wake();
  allow_completion = true;
  dispatcher.RunToCompletion();
  EXPECT_EQ(poll_count, 2);
}

TEST(FuncTask, DeducesValueInsteadOfReference) {
  auto callable = [](Context&) -> Poll<> { return Ready(); };
  FuncTask value_from_ref(callable);
  static_assert(
      std::is_same_v<decltype(value_from_ref), FuncTask<decltype(callable)>>);

  FuncTask<decltype(callable)&> explicit_ref(callable);
  static_assert(
      std::is_same_v<decltype(explicit_ref), FuncTask<decltype(callable)&>>);

  FuncTask value_from_move(std::move(callable));
  static_assert(
      std::is_same_v<decltype(value_from_move), FuncTask<decltype(callable)>>);
}

TEST(FuncTask, HoldsPwFunctionWithEmptyTypeList) {
  FuncTask<> func_task([](Context&) -> Poll<> { return Ready(); });
  static_assert(std::is_same_v<decltype(func_task),
                               FuncTask<Function<Poll<>(Context&)>>>);
}

Poll<> ReturnsReady(Context&) { return Ready(); }

// Simulates the size of a FuncTask for testing purposes.
template <typename Func>
struct SizeHelper : public Task {
  Func func;
};

TEST(FuncTask, TestTemplateDeductionAndSize) {
  // A FuncTask with an unspecified Func template parameter will default
  // to pw::Function. This allows the same container to hold a variety of
  // different callables, but it may either reserve extra inline storage or
  // dynamically allocate memory, depending on how pw::Function is configured.
  std::optional<FuncTask<>> a;
  a.emplace([](Context&) -> Poll<> { return Ready(); });
  a.emplace(&ReturnsReady);
  static_assert(sizeof(decltype(a)::value_type) ==
                sizeof(SizeHelper<Function<Poll<>(Context&)>>));

  // When constructing a FuncTask directly from a callable, CTAD will match
  // the Func template parameter to that of the callable. This has the
  // benefit of reducing the amount of storage needed vs that of a pw::Function.
  //
  // A lambda without any captures doesn't require any storage.
  auto b = FuncTask([](Context&) -> Poll<> { return Ready(); });
  static_assert(sizeof(decltype(b)) <= sizeof(SizeHelper<char>));

  // A lambda with captures requires storage to hold the captures.
  int scratch = 6;
  auto c = FuncTask(
      [&scratch](Context&) -> Poll<> { return scratch ? Ready() : Pending(); });
  static_assert(sizeof(decltype(c)) == sizeof(SizeHelper<int*>));

  // A raw function pointer just needs storage for the pointer value.
  auto d = FuncTask(&ReturnsReady);
  static_assert(sizeof(decltype(d)) ==
                sizeof(SizeHelper<decltype(&ReturnsReady)>));
}

TEST(FuncTask, DeregistersInDestructor) {
  DispatcherForTest dispatcher;
  {
    FuncTask task([](Context&) { return Pending(); });
    dispatcher.Post(task);
  }
  EXPECT_FALSE(dispatcher.RunUntilStalled());
}

TEST(RunOnce, VoidReturn) {
  DispatcherForTest dispatcher;

  int count = 0;
  RunOnceTask task([&count] { count += 1; });

  dispatcher.Post(task);
  dispatcher.RunToCompletion();

  EXPECT_EQ(count, 1);
}

TEST(RunOnce, ReturnValue) {
  DispatcherForTest dispatcher;

  int count = 0;
  RunOnceTask task([&count] {
    count += 1;
    return "o-}-<";
  });

  dispatcher.Post(task);
  dispatcher.RunToCompletion();

  EXPECT_STREQ(task.value(), "o-}-<");
}

TEST(RunOnce, VoidReturnValue) {
  DispatcherForTest dispatcher;

  int count = 0;
  RunOnceTask<pw::Function<void()>, pw::async2::ReturnValuePolicy::kKeep> task(
      [&count] { count += 1; });

  dispatcher.Post(task);

  EXPECT_FALSE(task.has_value());
  dispatcher.RunToCompletion();
  EXPECT_TRUE(task.has_value());
  static_assert(
      std::is_same_v<decltype(task)::value_type, pw::async2::ReadyType>);
}

TEST(RunOnce, DiscardNonVoidReturnValue) {
  DispatcherForTest dispatcher;

  int count = 0;
  auto func = [&count]() -> long long {
    count += 1;
    return -count;
  };

  RunOnceTask<decltype(func), pw::async2::ReturnValuePolicy::kDiscard> task(
      std::move(func));

  dispatcher.Post(task);
  dispatcher.RunToCompletion();
  task.Join();

  EXPECT_EQ(count, 1);
}

TEST(RunOnce, RunMultipleTimes) {
  DispatcherForTest dispatcher;

  int count = 0;
  RunOnceTask task([&count] {
    count += 1;
    return -count;
  });

  dispatcher.Post(task);
  dispatcher.RunToCompletion();

  EXPECT_EQ(count, 1);
  ASSERT_TRUE(task.has_value());
  EXPECT_EQ(task.value(), -1);

  dispatcher.Post(task);
  dispatcher.RunToCompletion();

  EXPECT_EQ(task.Wait(), -2);
  EXPECT_EQ(count, 2);
}

TEST(RunOnce, DeregistersInDestructor) {
  DispatcherForTest dispatcher;
  bool ran = false;
  {
    RunOnceTask task([&ran] { ran = true; });
    dispatcher.Post(task);
  }
  dispatcher.RunToCompletion();
  EXPECT_FALSE(ran);
}

}  // namespace
