//
// Copyright 2018 The Abseil 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.
//
// -----------------------------------------------------------------------------
// File: bit_gen_ref.h
// -----------------------------------------------------------------------------
//
// This header defines a bit generator "reference" class, for use in interfaces
// that take both Abseil (e.g. `absl::BitGen`) and standard library (e.g.
// `std::mt19937`) bit generators.

#ifndef ABSL_RANDOM_BIT_GEN_REF_H_
#define ABSL_RANDOM_BIT_GEN_REF_H_

#include "absl/base/internal/fast_type_id.h"
#include "absl/base/macros.h"
#include "absl/meta/type_traits.h"
#include "absl/random/internal/distribution_caller.h"
#include "absl/random/internal/fast_uniform_bits.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace random_internal {

template <typename URBG, typename = void, typename = void, typename = void>
struct is_urbg : std::false_type {};

template <typename URBG>
struct is_urbg<
    URBG,
    absl::enable_if_t<std::is_same<
        typename URBG::result_type,
        typename std::decay<decltype((URBG::min)())>::type>::value>,
    absl::enable_if_t<std::is_same<
        typename URBG::result_type,
        typename std::decay<decltype((URBG::max)())>::type>::value>,
    absl::enable_if_t<std::is_same<
        typename URBG::result_type,
        typename std::decay<decltype(std::declval<URBG>()())>::type>::value>>
    : std::true_type {};

template <typename>
struct DistributionCaller;
class MockHelpers;

}  // namespace random_internal

// -----------------------------------------------------------------------------
// absl::BitGenRef
// -----------------------------------------------------------------------------
//
// `absl::BitGenRef` is a type-erasing class that provides a generator-agnostic
// non-owning "reference" interface for use in place of any specific uniform
// random bit generator (URBG). This class may be used for both Abseil
// (e.g. `absl::BitGen`, `absl::InsecureBitGen`) and Standard library (e.g
// `std::mt19937`, `std::minstd_rand`) bit generators.
//
// Like other reference classes, `absl::BitGenRef` does not own the
// underlying bit generator, and the underlying instance must outlive the
// `absl::BitGenRef`.
//
// `absl::BitGenRef` is particularly useful when used with an
// `absl::MockingBitGen` to test specific paths in functions which use random
// values.
//
// Example:
//    void TakesBitGenRef(absl::BitGenRef gen) {
//      int x = absl::Uniform<int>(gen, 0, 1000);
//    }
//
class BitGenRef {
  // SFINAE to detect whether the URBG type includes a member matching
  // bool InvokeMock(base_internal::FastTypeIdType, void*, void*).
  //
  // These live inside BitGenRef so that they have friend access
  // to MockingBitGen. (see similar methods in DistributionCaller).
  template <template <class...> class Trait, class AlwaysVoid, class... Args>
  struct detector : std::false_type {};
  template <template <class...> class Trait, class... Args>
  struct detector<Trait, absl::void_t<Trait<Args...>>, Args...>
      : std::true_type {};

  template <class T>
  using invoke_mock_t = decltype(std::declval<T*>()->InvokeMock(
      std::declval<base_internal::FastTypeIdType>(), std::declval<void*>(),
      std::declval<void*>()));

  template <typename T>
  using HasInvokeMock = typename detector<invoke_mock_t, void, T>::type;

 public:
  BitGenRef(const BitGenRef&) = default;
  BitGenRef(BitGenRef&&) = default;
  BitGenRef& operator=(const BitGenRef&) = default;
  BitGenRef& operator=(BitGenRef&&) = default;

  template <typename URBG, typename absl::enable_if_t<
                               (!std::is_same<URBG, BitGenRef>::value &&
                                random_internal::is_urbg<URBG>::value &&
                                !HasInvokeMock<URBG>::value)>* = nullptr>
  BitGenRef(URBG& gen)  // NOLINT
      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
        mock_call_(NotAMock),
        generate_impl_fn_(ImplFn<URBG>) {}

  template <typename URBG,
            typename absl::enable_if_t<(!std::is_same<URBG, BitGenRef>::value &&
                                        random_internal::is_urbg<URBG>::value &&
                                        HasInvokeMock<URBG>::value)>* = nullptr>
  BitGenRef(URBG& gen)  // NOLINT
      : t_erased_gen_ptr_(reinterpret_cast<uintptr_t>(&gen)),
        mock_call_(&MockCall<URBG>),
        generate_impl_fn_(ImplFn<URBG>) {}

  using result_type = uint64_t;

  static constexpr result_type(min)() {
    return (std::numeric_limits<result_type>::min)();
  }

  static constexpr result_type(max)() {
    return (std::numeric_limits<result_type>::max)();
  }

  result_type operator()() { return generate_impl_fn_(t_erased_gen_ptr_); }

 private:
  using impl_fn = result_type (*)(uintptr_t);
  using mock_call_fn = bool (*)(uintptr_t, base_internal::FastTypeIdType, void*,
                                void*);

  template <typename URBG>
  static result_type ImplFn(uintptr_t ptr) {
    // Ensure that the return values from operator() fill the entire
    // range promised by result_type, min() and max().
    absl::random_internal::FastUniformBits<result_type> fast_uniform_bits;
    return fast_uniform_bits(*reinterpret_cast<URBG*>(ptr));
  }

  // Get a type-erased InvokeMock pointer.
  template <typename URBG>
  static bool MockCall(uintptr_t gen_ptr, base_internal::FastTypeIdType type,
                       void* result, void* arg_tuple) {
    return reinterpret_cast<URBG*>(gen_ptr)->InvokeMock(type, result,
                                                        arg_tuple);
  }
  static bool NotAMock(uintptr_t, base_internal::FastTypeIdType, void*, void*) {
    return false;
  }

  inline bool InvokeMock(base_internal::FastTypeIdType type, void* args_tuple,
                         void* result) {
    if (mock_call_ == NotAMock) return false;  // avoids an indirect call.
    return mock_call_(t_erased_gen_ptr_, type, args_tuple, result);
  }

  uintptr_t t_erased_gen_ptr_;
  mock_call_fn mock_call_;
  impl_fn generate_impl_fn_;

  template <typename>
  friend struct ::absl::random_internal::DistributionCaller;  // for InvokeMock
  friend class ::absl::random_internal::MockHelpers;          // for InvokeMock
};

ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_RANDOM_BIT_GEN_REF_H_
