#include <array>
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <tuple>
#include <vector>

#include "benchmark/benchmark.h"

#include "CartesianBenchmarks.h"
#include "GenerateInput.h"

namespace {

template <typename I, typename N>
std::array<I, 10> every_10th_percentile_N(I first, N n) {
  N step = n / 10;
  std::array<I, 10> res;

  for (size_t i = 0; i < 10; ++i) {
    res[i] = first;
    std::advance(first, step);
  }

  return res;
}

template <class IntT>
struct TestIntBase {
  static std::vector<IntT> generateInput(size_t size) {
    std::vector<IntT> Res(size);
    std::generate(Res.begin(), Res.end(),
                  [] { return getRandomInteger<IntT>(); });
    return Res;
  }
};

struct TestInt32 : TestIntBase<std::int32_t> {
  static constexpr const char* Name = "TestInt32";
};

struct TestInt64 : TestIntBase<std::int64_t> {
  static constexpr const char* Name = "TestInt64";
};

struct TestUint32 : TestIntBase<std::uint32_t> {
  static constexpr const char* Name = "TestUint32";
};

struct TestMediumString {
  static constexpr const char* Name = "TestMediumString";
  static constexpr size_t StringSize = 32;

  static std::vector<std::string> generateInput(size_t size) {
    std::vector<std::string> Res(size);
    std::generate(Res.begin(), Res.end(), [] { return getRandomString(StringSize); });
    return Res;
  }
};

using AllTestTypes = std::tuple<TestInt32, TestInt64, TestUint32, TestMediumString>;

struct LowerBoundAlg {
  template <class I, class V>
  I operator()(I first, I last, const V& value) const {
    return std::lower_bound(first, last, value);
  }

  static constexpr const char* Name = "LowerBoundAlg";
};

struct UpperBoundAlg {
  template <class I, class V>
  I operator()(I first, I last, const V& value) const {
    return std::upper_bound(first, last, value);
  }

  static constexpr const char* Name = "UpperBoundAlg";
};

struct EqualRangeAlg {
  template <class I, class V>
  std::pair<I, I> operator()(I first, I last, const V& value) const {
    return std::equal_range(first, last, value);
  }

  static constexpr const char* Name = "EqualRangeAlg";
};

using AllAlgs = std::tuple<LowerBoundAlg, UpperBoundAlg, EqualRangeAlg>;

template <class Alg, class TestType>
struct PartitionPointBench {
  size_t Quantity;

  std::string name() const {
    return std::string("PartitionPointBench_") + Alg::Name + "_" +
           TestType::Name + '/' + std::to_string(Quantity);
  }

  void run(benchmark::State& state) const {
    auto Data = TestType::generateInput(Quantity);
    std::sort(Data.begin(), Data.end());
    auto Every10Percentile = every_10th_percentile_N(Data.begin(), Data.size());

    for (auto _ : state) {
      for (auto Test : Every10Percentile)
        benchmark::DoNotOptimize(Alg{}(Data.begin(), Data.end(), *Test));
    }
  }
};

} // namespace

int main(int argc, char** argv) {
  benchmark::Initialize(&argc, argv);
  if (benchmark::ReportUnrecognizedArguments(argc, argv))
    return 1;

  const std::vector<size_t> Quantities = {1 << 8, 1 << 10, 1 << 20};
  makeCartesianProductBenchmark<PartitionPointBench, AllAlgs, AllTestTypes>(
      Quantities);
  benchmark::RunSpecifiedBenchmarks();
}
