// Copyright 2021 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.
#pragma once

#include <chrono>
#include <mutex>
#include <optional>
#include <type_traits>

#include "pw_assert/assert.h"
#include "pw_sync/virtual_basic_lockable.h"

namespace pw::sync {

// The BorrowedPointer is an RAII handle which wraps a pointer to a borrowed
// object along with a held lock which is guarding the object. When destroyed,
// the lock is released.
template <typename GuardedType, typename Lock = pw::sync::VirtualBasicLockable>
class BorrowedPointer {
 public:
  // Release the lock on destruction.
  ~BorrowedPointer() = default;

  // This object is moveable, but not copyable.
  //
  // Postcondition: The other BorrowedPointer is no longer valid and will assert
  //     if the GuardedType is accessed.
  BorrowedPointer(BorrowedPointer&& other)
      : unique_lock_(std::move(other.unique_lock_)), object_(other.object_) {
    other.object_ = nullptr;
  }
  BorrowedPointer& operator=(BorrowedPointer&& other) {
    unique_lock_ = std::move(other.unique_lock_);
    object_ = other.object_;
    other.object_ = nullptr;
    return *this;
  }
  BorrowedPointer(const BorrowedPointer&) = delete;
  BorrowedPointer& operator=(const BorrowedPointer&) = delete;

  // Provides access to the borrowed object's members.
  GuardedType* operator->() {
    PW_ASSERT(object_ != nullptr);  // Ensure this isn't a stale moved instance.
    return object_;
  }

  // Provides access to the borrowed object directly.
  //
  // NOTE: The member of pointer member access operator, operator->(), is
  // recommended over this API as this is prone to leaking references. However,
  // this is sometimes necessary.
  //
  // WARNING: Be careful not to leak references to the borrowed object!
  GuardedType& operator*() {
    PW_ASSERT(object_ != nullptr);  // Ensure this isn't a stale moved instance.
    return *object_;
  }

 private:
  // Allow BorrowedPointer creation inside of Borrowable's acquire methods.
  template <typename G, typename L>
  friend class Borrowable;

  BorrowedPointer(std::unique_lock<Lock> unique_lock, GuardedType* object)
      : unique_lock_(std::move(unique_lock)), object_(object) {}

  std::unique_lock<Lock> unique_lock_;
  GuardedType* object_;
};

// The Borrowable is a helper construct that enables callers to borrow an object
// which is guarded by a lock.
//
// Users who need access to the guarded object can ask to acquire a
// BorrowedPointer which permits access while the lock is held.
//
// This class is compatible with locks which comply with BasicLockable,
// Lockable, and TimedLockable C++ named requirements.
template <typename GuardedType, typename Lock = pw::sync::VirtualBasicLockable>
class Borrowable {
 public:
  constexpr Borrowable(GuardedType& object, Lock& lock)
      : lock_(&lock), object_(&object) {}

  Borrowable(const Borrowable&) = default;
  Borrowable& operator=(const Borrowable&) = default;
  Borrowable(Borrowable&& other) = default;
  Borrowable& operator=(Borrowable&& other) = default;

  // Blocks indefinitely until the object can be borrowed. Failures are fatal.
  BorrowedPointer<GuardedType, Lock> acquire() {
    std::unique_lock unique_lock(*lock_);
    return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
  }

  // Tries to borrow the object in a non-blocking manner. Returns a
  // BorrowedPointer on success, otherwise std::nullopt (nothing).
  std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire() {
    std::unique_lock unique_lock(*lock_, std::defer_lock);
    if (!unique_lock.try_lock()) {
      return std::nullopt;
    }
    return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
  }

  // Tries to borrow the object. Blocks until the specified timeout has elapsed
  // or the object has been borrowed, whichever comes first. Returns a
  // BorrowedPointer on success, otherwise std::nullopt (nothing).
  template <class Rep, class Period>
  std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire_for(
      std::chrono::duration<Rep, Period> timeout) {
    std::unique_lock unique_lock(*lock_, std::defer_lock);
    if (!unique_lock.try_lock_for(timeout)) {
      return std::nullopt;
    }
    return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
  }

  // Tries to borrow the object. Blocks until the specified deadline has passed
  // or the object has been borrowed, whichever comes first. Returns a
  // BorrowedPointer on success, otherwise std::nullopt (nothing).
  template <class Clock, class Duration>
  std::optional<BorrowedPointer<GuardedType, Lock>> try_acquire_until(
      std::chrono::time_point<Clock, Duration> deadline) {
    std::unique_lock unique_lock(*lock_, std::defer_lock);
    if (!unique_lock.try_lock_until(deadline)) {
      return std::nullopt;
    }
    return BorrowedPointer<GuardedType, Lock>(std::move(unique_lock), object_);
  }

 private:
  Lock* lock_;
  GuardedType* object_;
};

}  // namespace pw::sync
