// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef LIB_FIT_DEFER_H_
#define LIB_FIT_DEFER_H_

#include <utility>

#include "function.h"
#include "nullable.h"

namespace fit {

// A move-only deferred action wrapper with RAII semantics.
// This class is not thread safe.
//
// The wrapper holds a function-like callable target with no arguments
// which it invokes when it goes out of scope unless canceled, called, or
// moved to a wrapper in a different scope.
//
// See |fit::defer()| for idiomatic usage.
template <typename T>
class deferred_action final {
 public:
  // Creates a deferred action without a pending target.
  deferred_action() = default;
  explicit deferred_action(decltype(nullptr)) {}

  // Creates a deferred action with a pending target.
  explicit deferred_action(T target) : target_(std::move(target)) {}

  // Creates a deferred action with a pending target moved from another
  // deferred action, leaving the other one without a pending target.
  deferred_action(deferred_action&& other) : target_(std::move(other.target_)) {
    other.target_.reset();
  }

  // Invokes and releases the deferred action's pending target (if any).
  ~deferred_action() { call(); }

  // Returns true if the deferred action has a pending target.
  explicit operator bool() const { return !!target_; }

  // Invokes and releases the deferred action's pending target (if any),
  // then move-assigns it from another deferred action, leaving the latter
  // one without a pending target.
  deferred_action& operator=(deferred_action&& other) {
    if (&other == this)
      return *this;
    call();
    target_ = std::move(other.target_);
    other.target_.reset();
    return *this;
  }

  // Invokes and releases the deferred action's pending target (if any).
  void call() {
    if (target_) {
      // Move to a local to guard against re-entrance.
      T local_target = std::move(*target_);
      target_.reset();
      local_target();
    }
  }

  // Releases the deferred action's pending target (if any) without
  // invoking it.
  void cancel() { target_.reset(); }
  deferred_action& operator=(decltype(nullptr)) {
    cancel();
    return *this;
  }

  // Assigns a new target to the deferred action.
  deferred_action& operator=(T target) {
    target_ = std::move(target);
    return *this;
  }

  deferred_action(const deferred_action& other) = delete;
  deferred_action& operator=(const deferred_action& other) = delete;

 private:
  nullable<T> target_;
};

template <typename T>
bool operator==(const deferred_action<T>& action, decltype(nullptr)) {
  return !action;
}
template <typename T>
bool operator==(decltype(nullptr), const deferred_action<T>& action) {
  return !action;
}
template <typename T>
bool operator!=(const deferred_action<T>& action, decltype(nullptr)) {
  return !!action;
}
template <typename T>
bool operator!=(decltype(nullptr), const deferred_action<T>& action) {
  return !!action;
}

// Defers execution of a function-like callable target with no arguments
// until the value returned by this function goes out of scope unless canceled,
// called, or moved to a wrapper in a different scope.
//
// // This example prints "Hello..." then "Goodbye!".
// void test() {
//     auto d = fit::defer([]{ puts("Goodbye!"); });
//     puts("Hello...");
// }
//
// // This example prints nothing because the deferred action is canceled.
// void do_nothing() {
//     auto d = fit::defer([]{ puts("I'm not here."); });
//     d.cancel();
// }
//
// // This example shows how the deferred action can be reassigned assuming
// // the new target has the same type and the old one, in this case by
// // representing the target as a |fit::closure|.
// void reassign() {
//     auto d = fit::defer<fit::closure>([] { puts("This runs first."); });
//     d = fit::defer<fit::closure>([] { puts("This runs afterwards."); });
// }
template <typename T>
inline deferred_action<T> defer(T target) {
  return deferred_action<T>(std::move(target));
}

// Alias for a deferred_action using a fit::callback.
using deferred_callback = deferred_action<fit::callback<void()>>;

// Defers execution of a fit::callback with no arguments. See |fit::defer| for
// details.
inline deferred_callback defer_callback(fit::callback<void()> target) {
  return deferred_callback(std::move(target));
}

}  // namespace fit

#endif  // LIB_FIT_DEFER_H_
