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

// This module defines an abstract interface for iterating through pages in a
// Parquet column chunk within a row group. It could be extended in the future
// to iterate through all data pages in all chunks in a file.

#ifndef PARQUET_COLUMN_TEST_UTIL_H
#define PARQUET_COLUMN_TEST_UTIL_H

#include <algorithm>
#include <limits>
#include <memory>
#include <string>
#include <vector>

#include <gtest/gtest.h>

#include "parquet/column_page.h"
#include "parquet/column_reader.h"
#include "parquet/column_writer.h"
#include "parquet/encoding-internal.h"
#include "parquet/util/memory.h"
#include "parquet/util/test-common.h"

using std::vector;
using std::shared_ptr;

namespace parquet {

static int FLBA_LENGTH = 12;

bool operator==(const FixedLenByteArray& a, const FixedLenByteArray& b) {
  return 0 == memcmp(a.ptr, b.ptr, FLBA_LENGTH);
}

namespace test {

template <typename T>
static void InitValues(int num_values, vector<T>& values, vector<uint8_t>& buffer) {
  random_numbers(num_values, 0, std::numeric_limits<T>::min(),
      std::numeric_limits<T>::max(), values.data());
}

template <typename T>
static void InitDictValues(
    int num_values, int num_dicts, vector<T>& values, vector<uint8_t>& buffer) {
  int repeat_factor = num_values / num_dicts;
  InitValues<T>(num_dicts, values, buffer);
  // add some repeated values
  for (int j = 1; j < repeat_factor; ++j) {
    for (int i = 0; i < num_dicts; ++i) {
      std::memcpy(&values[num_dicts * j + i], &values[i], sizeof(T));
    }
  }
  // computed only dict_per_page * repeat_factor - 1 values < num_values
  // compute remaining
  for (int i = num_dicts * repeat_factor; i < num_values; ++i) {
    std::memcpy(&values[i], &values[i - num_dicts * repeat_factor], sizeof(T));
  }
}

class MockPageReader : public PageReader {
 public:
  explicit MockPageReader(const vector<shared_ptr<Page>>& pages)
      : pages_(pages), page_index_(0) {}

  // Implement the PageReader interface
  virtual shared_ptr<Page> NextPage() {
    if (page_index_ == static_cast<int>(pages_.size())) {
      // EOS to consumer
      return shared_ptr<Page>(nullptr);
    }
    return pages_[page_index_++];
  }

 private:
  vector<shared_ptr<Page>> pages_;
  int page_index_;
};

// TODO(wesm): this is only used for testing for now. Refactor to form part of
// primary file write path
template <typename Type>
class DataPageBuilder {
 public:
  typedef typename Type::c_type T;

  // This class writes data and metadata to the passed inputs
  explicit DataPageBuilder(InMemoryOutputStream* sink)
      : sink_(sink),
        num_values_(0),
        encoding_(Encoding::PLAIN),
        definition_level_encoding_(Encoding::RLE),
        repetition_level_encoding_(Encoding::RLE),
        have_def_levels_(false),
        have_rep_levels_(false),
        have_values_(false) {}

  void AppendDefLevels(const vector<int16_t>& levels, int16_t max_level,
      Encoding::type encoding = Encoding::RLE) {
    AppendLevels(levels, max_level, encoding);

    num_values_ = std::max(static_cast<int32_t>(levels.size()), num_values_);
    definition_level_encoding_ = encoding;
    have_def_levels_ = true;
  }

  void AppendRepLevels(const vector<int16_t>& levels, int16_t max_level,
      Encoding::type encoding = Encoding::RLE) {
    AppendLevels(levels, max_level, encoding);

    num_values_ = std::max(static_cast<int32_t>(levels.size()), num_values_);
    repetition_level_encoding_ = encoding;
    have_rep_levels_ = true;
  }

  void AppendValues(const ColumnDescriptor* d, const vector<T>& values,
      Encoding::type encoding = Encoding::PLAIN) {
    PlainEncoder<Type> encoder(d);
    encoder.Put(&values[0], static_cast<int>(values.size()));
    std::shared_ptr<Buffer> values_sink = encoder.FlushValues();
    sink_->Write(values_sink->data(), values_sink->size());

    num_values_ = std::max(static_cast<int32_t>(values.size()), num_values_);
    encoding_ = encoding;
    have_values_ = true;
  }

  int32_t num_values() const { return num_values_; }

  Encoding::type encoding() const { return encoding_; }

  Encoding::type rep_level_encoding() const { return repetition_level_encoding_; }

  Encoding::type def_level_encoding() const { return definition_level_encoding_; }

 private:
  InMemoryOutputStream* sink_;

  int32_t num_values_;
  Encoding::type encoding_;
  Encoding::type definition_level_encoding_;
  Encoding::type repetition_level_encoding_;

  bool have_def_levels_;
  bool have_rep_levels_;
  bool have_values_;

  // Used internally for both repetition and definition levels
  void AppendLevels(
      const vector<int16_t>& levels, int16_t max_level, Encoding::type encoding) {
    if (encoding != Encoding::RLE) {
      ParquetException::NYI("only rle encoding currently implemented");
    }

    // TODO: compute a more precise maximum size for the encoded levels
    vector<uint8_t> encode_buffer(levels.size() * 2);

    // We encode into separate memory from the output stream because the
    // RLE-encoded bytes have to be preceded in the stream by their absolute
    // size.
    LevelEncoder encoder;
    encoder.Init(encoding, max_level, static_cast<int>(levels.size()),
        encode_buffer.data(), static_cast<int>(encode_buffer.size()));

    encoder.Encode(static_cast<int>(levels.size()), levels.data());

    int32_t rle_bytes = encoder.len();
    sink_->Write(reinterpret_cast<const uint8_t*>(&rle_bytes), sizeof(int32_t));
    sink_->Write(encode_buffer.data(), rle_bytes);
  }
};

template <>
void DataPageBuilder<BooleanType>::AppendValues(
    const ColumnDescriptor* d, const vector<bool>& values, Encoding::type encoding) {
  if (encoding != Encoding::PLAIN) {
    ParquetException::NYI("only plain encoding currently implemented");
  }
  PlainEncoder<BooleanType> encoder(d);
  encoder.Put(values, static_cast<int>(values.size()));
  std::shared_ptr<Buffer> buffer = encoder.FlushValues();
  sink_->Write(buffer->data(), buffer->size());

  num_values_ = std::max(static_cast<int32_t>(values.size()), num_values_);
  encoding_ = encoding;
  have_values_ = true;
}

template <typename Type>
static shared_ptr<DataPage> MakeDataPage(const ColumnDescriptor* d,
    const vector<typename Type::c_type>& values, int num_vals, Encoding::type encoding,
    const uint8_t* indices, int indices_size, const vector<int16_t>& def_levels,
    int16_t max_def_level, const vector<int16_t>& rep_levels, int16_t max_rep_level) {
  int num_values = 0;

  InMemoryOutputStream page_stream;
  test::DataPageBuilder<Type> page_builder(&page_stream);

  if (!rep_levels.empty()) { page_builder.AppendRepLevels(rep_levels, max_rep_level); }
  if (!def_levels.empty()) { page_builder.AppendDefLevels(def_levels, max_def_level); }

  if (encoding == Encoding::PLAIN) {
    page_builder.AppendValues(d, values, encoding);
    num_values = page_builder.num_values();
  } else {  // DICTIONARY PAGES
    page_stream.Write(indices, indices_size);
    num_values = std::max(page_builder.num_values(), num_vals);
  }

  auto buffer = page_stream.GetBuffer();

  return std::make_shared<DataPage>(buffer, num_values, encoding,
      page_builder.def_level_encoding(), page_builder.rep_level_encoding());
}

template <typename TYPE>
class DictionaryPageBuilder {
 public:
  typedef typename TYPE::c_type TC;
  static constexpr int TN = TYPE::type_num;

  // This class writes data and metadata to the passed inputs
  explicit DictionaryPageBuilder(const ColumnDescriptor* d)
      : num_dict_values_(0), have_values_(false) {
    encoder_.reset(new DictEncoder<TYPE>(d, &pool_));
  }

  ~DictionaryPageBuilder() { pool_.FreeAll(); }

  shared_ptr<Buffer> AppendValues(const vector<TC>& values) {
    int num_values = static_cast<int>(values.size());
    // Dictionary encoding
    encoder_->Put(values.data(), num_values);
    num_dict_values_ = encoder_->num_entries();
    have_values_ = true;
    return encoder_->FlushValues();
  }

  shared_ptr<Buffer> WriteDict() {
    std::shared_ptr<PoolBuffer> dict_buffer =
        AllocateBuffer(::arrow::default_memory_pool(), encoder_->dict_encoded_size());
    encoder_->WriteDict(dict_buffer->mutable_data());
    return dict_buffer;
  }

  int32_t num_values() const { return num_dict_values_; }

 private:
  ChunkedAllocator pool_;
  shared_ptr<DictEncoder<TYPE>> encoder_;
  int32_t num_dict_values_;
  bool have_values_;
};

template <>
DictionaryPageBuilder<BooleanType>::DictionaryPageBuilder(const ColumnDescriptor* d) {
  ParquetException::NYI("only plain encoding currently implemented for boolean");
}

template <>
shared_ptr<Buffer> DictionaryPageBuilder<BooleanType>::WriteDict() {
  ParquetException::NYI("only plain encoding currently implemented for boolean");
  return nullptr;
}

template <>
shared_ptr<Buffer> DictionaryPageBuilder<BooleanType>::AppendValues(
    const vector<TC>& values) {
  ParquetException::NYI("only plain encoding currently implemented for boolean");
  return nullptr;
}

template <typename Type>
static shared_ptr<DictionaryPage> MakeDictPage(const ColumnDescriptor* d,
    const vector<typename Type::c_type>& values, const vector<int>& values_per_page,
    Encoding::type encoding, vector<shared_ptr<Buffer>>& rle_indices) {
  InMemoryOutputStream page_stream;
  test::DictionaryPageBuilder<Type> page_builder(d);
  int num_pages = static_cast<int>(values_per_page.size());
  int value_start = 0;

  for (int i = 0; i < num_pages; i++) {
    rle_indices.push_back(page_builder.AppendValues(
        slice(values, value_start, value_start + values_per_page[i])));
    value_start += values_per_page[i];
  }

  auto buffer = page_builder.WriteDict();

  return std::make_shared<DictionaryPage>(
      buffer, page_builder.num_values(), Encoding::PLAIN);
}

// Given def/rep levels and values create multiple dict pages
template <typename Type>
static void PaginateDict(const ColumnDescriptor* d,
    const vector<typename Type::c_type>& values, const vector<int16_t>& def_levels,
    int16_t max_def_level, const vector<int16_t>& rep_levels, int16_t max_rep_level,
    int num_levels_per_page, const vector<int>& values_per_page,
    vector<shared_ptr<Page>>& pages, Encoding::type encoding = Encoding::RLE_DICTIONARY) {
  int num_pages = static_cast<int>(values_per_page.size());
  vector<shared_ptr<Buffer>> rle_indices;
  shared_ptr<DictionaryPage> dict_page =
      MakeDictPage<Type>(d, values, values_per_page, encoding, rle_indices);
  pages.push_back(dict_page);
  int def_level_start = 0;
  int def_level_end = 0;
  int rep_level_start = 0;
  int rep_level_end = 0;
  for (int i = 0; i < num_pages; i++) {
    if (max_def_level > 0) {
      def_level_start = i * num_levels_per_page;
      def_level_end = (i + 1) * num_levels_per_page;
    }
    if (max_rep_level > 0) {
      rep_level_start = i * num_levels_per_page;
      rep_level_end = (i + 1) * num_levels_per_page;
    }
    shared_ptr<DataPage> data_page = MakeDataPage<Int32Type>(d, {}, values_per_page[i],
        encoding, rle_indices[i]->data(), static_cast<int>(rle_indices[i]->size()),
        slice(def_levels, def_level_start, def_level_end), max_def_level,
        slice(rep_levels, rep_level_start, rep_level_end), max_rep_level);
    pages.push_back(data_page);
  }
}

// Given def/rep levels and values create multiple plain pages
template <typename Type>
static void PaginatePlain(const ColumnDescriptor* d,
    const vector<typename Type::c_type>& values, const vector<int16_t>& def_levels,
    int16_t max_def_level, const vector<int16_t>& rep_levels, int16_t max_rep_level,
    int num_levels_per_page, const vector<int>& values_per_page,
    vector<shared_ptr<Page>>& pages, Encoding::type encoding = Encoding::PLAIN) {
  int num_pages = static_cast<int>(values_per_page.size());
  int def_level_start = 0;
  int def_level_end = 0;
  int rep_level_start = 0;
  int rep_level_end = 0;
  int value_start = 0;
  for (int i = 0; i < num_pages; i++) {
    if (max_def_level > 0) {
      def_level_start = i * num_levels_per_page;
      def_level_end = (i + 1) * num_levels_per_page;
    }
    if (max_rep_level > 0) {
      rep_level_start = i * num_levels_per_page;
      rep_level_end = (i + 1) * num_levels_per_page;
    }
    shared_ptr<DataPage> page = MakeDataPage<Type>(d,
        slice(values, value_start, value_start + values_per_page[i]), values_per_page[i],
        encoding, NULL, 0, slice(def_levels, def_level_start, def_level_end),
        max_def_level, slice(rep_levels, rep_level_start, rep_level_end), max_rep_level);
    pages.push_back(page);
    value_start += values_per_page[i];
  }
}

// Generates pages from randomly generated data
template <typename Type>
static int MakePages(const ColumnDescriptor* d, int num_pages, int levels_per_page,
    vector<int16_t>& def_levels, vector<int16_t>& rep_levels,
    vector<typename Type::c_type>& values, vector<uint8_t>& buffer,
    vector<shared_ptr<Page>>& pages, Encoding::type encoding = Encoding::PLAIN) {
  int num_levels = levels_per_page * num_pages;
  int num_values = 0;
  uint32_t seed = 0;
  int16_t zero = 0;
  int16_t max_def_level = d->max_definition_level();
  int16_t max_rep_level = d->max_repetition_level();
  vector<int> values_per_page(num_pages, levels_per_page);
  // Create definition levels
  if (max_def_level > 0) {
    def_levels.resize(num_levels);
    random_numbers(num_levels, seed, zero, max_def_level, def_levels.data());
    for (int p = 0; p < num_pages; p++) {
      int num_values_per_page = 0;
      for (int i = 0; i < levels_per_page; i++) {
        if (def_levels[i + p * levels_per_page] == max_def_level) {
          num_values_per_page++;
          num_values++;
        }
      }
      values_per_page[p] = num_values_per_page;
    }
  } else {
    num_values = num_levels;
  }
  // Create repitition levels
  if (max_rep_level > 0) {
    rep_levels.resize(num_levels);
    random_numbers(num_levels, seed, zero, max_rep_level, rep_levels.data());
  }
  // Create values
  values.resize(num_values);
  if (encoding == Encoding::PLAIN) {
    InitValues<typename Type::c_type>(num_values, values, buffer);
    PaginatePlain<Type>(d, values, def_levels, max_def_level, rep_levels, max_rep_level,
        levels_per_page, values_per_page, pages);
  } else if (encoding == Encoding::RLE_DICTIONARY ||
             encoding == Encoding::PLAIN_DICTIONARY) {
    // Calls InitValues and repeats the data
    InitDictValues<typename Type::c_type>(num_values, levels_per_page, values, buffer);
    PaginateDict<Type>(d, values, def_levels, max_def_level, rep_levels, max_rep_level,
        levels_per_page, values_per_page, pages);
  }

  return num_values;
}

}  // namespace test

}  // namespace parquet

#endif  // PARQUET_COLUMN_TEST_UTIL_H
