// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you 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
//
//   http://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.

#include "benchmark/benchmark.h"

#include <cstdint>
#include <cstdlib>
#include <memory>

#include "arrow/array/array_base.h"
#include "arrow/array/array_primitive.h"
#include "arrow/testing/random.h"
#include "arrow/util/bit_block_counter.h"
#include "arrow/util/bit_util.h"
#include "arrow/util/bitmap_reader.h"

namespace arrow {
namespace internal {

struct UnaryBitBlockBenchmark {
  benchmark::State& state;
  int64_t offset;
  int64_t bitmap_length;
  std::shared_ptr<Array> arr;
  int64_t expected;

  explicit UnaryBitBlockBenchmark(benchmark::State& state, int64_t offset = 0)
      : state(state), offset(offset), bitmap_length(1 << 20) {
    random::RandomArrayGenerator rng(/*seed=*/0);
    // State parameter is the average number of total values for each null
    // value. So 100 means that 1 out of 100 on average are null.
    double null_probability = 1. / static_cast<double>(state.range(0));
    arr = rng.Int8(bitmap_length, 0, 100, null_probability);

    // Compute the expected result
    this->expected = 0;
    const auto& int8_arr = static_cast<const Int8Array&>(*arr);
    for (int64_t i = this->offset; i < bitmap_length; ++i) {
      if (int8_arr.IsValid(i)) {
        this->expected += int8_arr.Value(i);
      }
    }
  }

  template <typename NextBlockFunc>
  void BenchBitBlockCounter(NextBlockFunc&& next_block) {
    const auto& int8_arr = static_cast<const Int8Array&>(*arr);
    const uint8_t* bitmap = arr->null_bitmap_data();
    for (auto _ : state) {
      BitBlockCounter scanner(bitmap, this->offset, bitmap_length - this->offset);
      int64_t result = 0;
      int64_t position = this->offset;
      while (true) {
        BitBlockCount block = next_block(&scanner);
        if (block.length == 0) {
          break;
        }
        if (block.length == block.popcount) {
          // All not-null
          for (int64_t i = 0; i < block.length; ++i) {
            result += int8_arr.Value(position + i);
          }
        } else if (block.popcount > 0) {
          // Some but not all not-null
          for (int64_t i = 0; i < block.length; ++i) {
            if (BitUtil::GetBit(bitmap, position + i)) {
              result += int8_arr.Value(position + i);
            }
          }
        }
        position += block.length;
      }
      // Sanity check
      if (result != expected) {
        std::abort();
      }
    }
    state.SetItemsProcessed(state.iterations() * bitmap_length);
  }

  void BenchBitmapReader() {
    const auto& int8_arr = static_cast<const Int8Array&>(*arr);
    for (auto _ : state) {
      internal::BitmapReader bit_reader(arr->null_bitmap_data(), this->offset,
                                        bitmap_length - this->offset);
      int64_t result = 0;
      for (int64_t i = this->offset; i < bitmap_length; ++i) {
        if (bit_reader.IsSet()) {
          result += int8_arr.Value(i);
        }
        bit_reader.Next();
      }
      // Sanity check
      if (result != expected) {
        std::abort();
      }
    }
    state.SetItemsProcessed(state.iterations() * bitmap_length);
  }
};

struct BinaryBitBlockBenchmark {
  benchmark::State& state;
  int64_t offset;
  int64_t bitmap_length;
  std::shared_ptr<Array> left;
  std::shared_ptr<Array> right;
  int64_t expected;
  const Int8Array* left_int8;
  const Int8Array* right_int8;

  explicit BinaryBitBlockBenchmark(benchmark::State& state, int64_t offset = 0)
      : state(state), offset(offset), bitmap_length(1 << 20) {
    random::RandomArrayGenerator rng(/*seed=*/0);

    // State parameter is the average number of total values for each null
    // value. So 100 means that 1 out of 100 on average are null.
    double null_probability = 1. / static_cast<double>(state.range(0));
    left = rng.Int8(bitmap_length, 0, 100, null_probability);
    right = rng.Int8(bitmap_length, 0, 50, null_probability);
    left_int8 = static_cast<const Int8Array*>(left.get());
    right_int8 = static_cast<const Int8Array*>(right.get());

    // Compute the expected result
    expected = 0;
    for (int64_t i = this->offset; i < bitmap_length; ++i) {
      if (left_int8->IsValid(i) && right_int8->IsValid(i)) {
        expected += left_int8->Value(i) + right_int8->Value(i);
      }
    }
  }

  void BenchBitBlockCounter() {
    const uint8_t* left_bitmap = left->null_bitmap_data();
    const uint8_t* right_bitmap = right->null_bitmap_data();
    for (auto _ : state) {
      BinaryBitBlockCounter scanner(left_bitmap, this->offset, right_bitmap, this->offset,
                                    bitmap_length - this->offset);
      int64_t result = 0;
      int64_t position = this->offset;
      while (true) {
        BitBlockCount block = scanner.NextAndWord();
        if (block.length == 0) {
          break;
        }
        if (block.length == block.popcount) {
          // All not-null
          for (int64_t i = 0; i < block.length; ++i) {
            result += left_int8->Value(position + i) + right_int8->Value(position + i);
          }
        } else if (block.popcount > 0) {
          // Some but not all not-null
          for (int64_t i = 0; i < block.length; ++i) {
            if (BitUtil::GetBit(left_bitmap, position + i) &&
                BitUtil::GetBit(right_bitmap, position + i)) {
              result += left_int8->Value(position + i) + right_int8->Value(position + i);
            }
          }
        }
        position += block.length;
      }
      // Sanity check
      if (result != expected) {
        std::abort();
      }
    }
    state.SetItemsProcessed(state.iterations() * bitmap_length);
  }

  void BenchBitmapReader() {
    for (auto _ : state) {
      internal::BitmapReader left_reader(left->null_bitmap_data(), this->offset,
                                         bitmap_length - this->offset);
      internal::BitmapReader right_reader(right->null_bitmap_data(), this->offset,
                                          bitmap_length - this->offset);
      int64_t result = 0;
      for (int64_t i = this->offset; i < bitmap_length; ++i) {
        if (left_reader.IsSet() && right_reader.IsSet()) {
          result += left_int8->Value(i) + right_int8->Value(i);
        }
        left_reader.Next();
        right_reader.Next();
      }
      // Sanity check
      if (result != expected) {
        std::abort();
      }
    }
    state.SetItemsProcessed(state.iterations() * bitmap_length);
  }
};

static void BitBlockCounterSum(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/0)
      .BenchBitBlockCounter([](BitBlockCounter* counter) { return counter->NextWord(); });
}

static void BitBlockCounterSumWithOffset(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/4)
      .BenchBitBlockCounter([](BitBlockCounter* counter) { return counter->NextWord(); });
}

static void BitBlockCounterFourWordsSum(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/0)
      .BenchBitBlockCounter(
          [](BitBlockCounter* counter) { return counter->NextFourWords(); });
}

static void BitBlockCounterFourWordsSumWithOffset(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/4)
      .BenchBitBlockCounter(
          [](BitBlockCounter* counter) { return counter->NextFourWords(); });
}

static void BitmapReaderSum(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/0).BenchBitmapReader();
}

static void BitmapReaderSumWithOffset(benchmark::State& state) {
  UnaryBitBlockBenchmark(state, /*offset=*/4).BenchBitmapReader();
}

static void BinaryBitBlockCounterSum(benchmark::State& state) {
  BinaryBitBlockBenchmark(state, /*offset=*/0).BenchBitBlockCounter();
}

static void BinaryBitBlockCounterSumWithOffset(benchmark::State& state) {
  BinaryBitBlockBenchmark(state, /*offset=*/4).BenchBitBlockCounter();
}

static void BinaryBitmapReaderSum(benchmark::State& state) {
  BinaryBitBlockBenchmark(state, /*offset=*/0).BenchBitmapReader();
}

static void BinaryBitmapReaderSumWithOffset(benchmark::State& state) {
  BinaryBitBlockBenchmark(state, /*offset=*/4).BenchBitmapReader();
}

// Range value: average number of total values per null
BENCHMARK(BitBlockCounterSum)->Range(2, 1 << 16);
BENCHMARK(BitBlockCounterSumWithOffset)->Range(2, 1 << 16);
BENCHMARK(BitBlockCounterFourWordsSum)->Range(2, 1 << 16);
BENCHMARK(BitBlockCounterFourWordsSumWithOffset)->Range(2, 1 << 16);
BENCHMARK(BitmapReaderSum)->Range(2, 1 << 16);
BENCHMARK(BitmapReaderSumWithOffset)->Range(2, 1 << 16);
BENCHMARK(BinaryBitBlockCounterSum)->Range(2, 1 << 16);
BENCHMARK(BinaryBitBlockCounterSumWithOffset)->Range(2, 1 << 16);
BENCHMARK(BinaryBitmapReaderSum)->Range(2, 1 << 16);
BENCHMARK(BinaryBitmapReaderSumWithOffset)->Range(2, 1 << 16);

}  // namespace internal
}  // namespace arrow
