// 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.

#ifndef ABSL_CONTAINER_BTREE_TEST_H_
#define ABSL_CONTAINER_BTREE_TEST_H_

#include <algorithm>
#include <cassert>
#include <random>
#include <string>
#include <type_traits>
#include <utility>
#include <vector>

#include "absl/container/btree_map.h"
#include "absl/container/btree_set.h"
#include "absl/container/flat_hash_set.h"
#include "absl/strings/cord.h"
#include "absl/time/time.h"

namespace absl {
ABSL_NAMESPACE_BEGIN
namespace container_internal {

// Like remove_const but propagates the removal through std::pair.
template <typename T>
struct remove_pair_const {
  using type = std::remove_const_t<T>;
};
template <typename T, typename U>
struct remove_pair_const<std::pair<T, U> > {
  using type = std::pair<typename remove_pair_const<T>::type,
                         typename remove_pair_const<U>::type>;
};

// Utility class to provide an accessor for a key given a value. The default
// behavior is to treat the value as a pair and return the first element.
template <typename K, typename V>
struct KeyOfValue {
  struct type {
    const K& operator()(const V& p) const { return p.first; }
  };
};

// Partial specialization of KeyOfValue class for when the key and value are
// the same type such as in set<> and btree_set<>.
template <typename K>
struct KeyOfValue<K, K> {
  struct type {
    const K& operator()(const K& k) const { return k; }
  };
};

inline char* GenerateDigits(char buf[16], unsigned val, unsigned maxval) {
  assert(val <= maxval);
  constexpr unsigned kBase = 64;  // avoid integer division.
  unsigned p = 15;
  buf[p--] = 0;
  while (maxval > 0) {
    buf[p--] = ' ' + (val % kBase);
    val /= kBase;
    maxval /= kBase;
  }
  return buf + p + 1;
}

template <typename K>
struct Generator {
  int maxval;
  explicit Generator(int m) : maxval(m) {}
  K operator()(int i) const {
    assert(i <= maxval);
    return K(i);
  }
};

template <>
struct Generator<absl::Time> {
  int maxval;
  explicit Generator(int m) : maxval(m) {}
  absl::Time operator()(int i) const { return absl::FromUnixMillis(i); }
};

template <>
struct Generator<std::string> {
  int maxval;
  explicit Generator(int m) : maxval(m) {}
  std::string operator()(int i) const {
    char buf[16];
    return GenerateDigits(buf, i, maxval);
  }
};

template <>
struct Generator<Cord> {
  int maxval;
  explicit Generator(int m) : maxval(m) {}
  Cord operator()(int i) const {
    char buf[16];
    return Cord(GenerateDigits(buf, i, maxval));
  }
};

template <typename T, typename U>
struct Generator<std::pair<T, U> > {
  Generator<typename remove_pair_const<T>::type> tgen;
  Generator<typename remove_pair_const<U>::type> ugen;

  explicit Generator(int m) : tgen(m), ugen(m) {}
  std::pair<T, U> operator()(int i) const {
    return std::make_pair(tgen(i), ugen(i));
  }
};

// Generate n values for our tests and benchmarks. Value range is [0, maxval].
inline std::vector<int> GenerateNumbersWithSeed(int n, int maxval, int seed) {
  // NOTE: Some tests rely on generated numbers not changing between test runs.
  // We use std::minstd_rand0 because it is well-defined, but don't use
  // std::uniform_int_distribution because platforms use different algorithms.
  std::minstd_rand0 rng(seed);

  std::vector<int> values;
  absl::flat_hash_set<int> unique_values;
  if (values.size() < n) {
    for (int i = values.size(); i < n; i++) {
      int value;
      do {
        value = static_cast<int>(rng()) % (maxval + 1);
      } while (!unique_values.insert(value).second);

      values.push_back(value);
    }
  }
  return values;
}

// Generates n values in the range [0, maxval].
template <typename V>
std::vector<V> GenerateValuesWithSeed(int n, int maxval, int seed) {
  const std::vector<int> nums = GenerateNumbersWithSeed(n, maxval, seed);
  Generator<V> gen(maxval);
  std::vector<V> vec;

  vec.reserve(n);
  for (int i = 0; i < n; i++) {
    vec.push_back(gen(nums[i]));
  }

  return vec;
}

}  // namespace container_internal
ABSL_NAMESPACE_END
}  // namespace absl

#endif  // ABSL_CONTAINER_BTREE_TEST_H_
