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

#ifndef KUDU_CFILE_INDEX_BLOCK_H
#define KUDU_CFILE_INDEX_BLOCK_H

#include <cstddef>
#include <cstdint>
#include <vector>

#include "kudu/cfile/block_pointer.h"
#include "kudu/cfile/cfile.pb.h"
#include "kudu/gutil/macros.h"
#include "kudu/util/faststring.h"
#include "kudu/util/slice.h"
#include "kudu/util/status.h"

namespace kudu {
namespace cfile {

// Forward decl.
class IndexBlockIterator;

struct WriterOptions;

// Index Block Builder for a particular key type.
// This works like the rest of the builders in the cfile package.
// After repeatedly calling Add(), call Finish() to encode it
// into a Slice, then you may Reset to re-use buffers.
class IndexBlockBuilder {
 public:
  explicit IndexBlockBuilder(const WriterOptions *options,
                             bool is_leaf);

  // Append an entry into the index.
  void Add(const Slice &key, const BlockPointer &ptr);

  // Finish the current index block.
  // Returns a fully encoded Slice including the data
  // as well as any necessary footer.
  // The Slice is only valid until the next call to
  // Reset().
  Slice Finish();

  // Return the key of the first entry in this index block.
  // The pointed-to data is only valid until the next call to this builder.
  Status GetFirstKey(Slice *key) const;

  // Return the number of entries already added to this index
  // block.
  size_t count() const {
    return entry_offsets_.size();
  }

  // Return an estimate of the post-encoding size of this
  // index block. This estimate should be conservative --
  // it will over-estimate rather than under-estimate, and
  // should be accurate to within a reasonable threshold,
  // but is not exact.
  size_t EstimateEncodedSize() const;

  void Reset();

 private:
  DISALLOW_COPY_AND_ASSIGN(IndexBlockBuilder);

#ifdef __clang__
  __attribute__((__unused__))
#endif
  const WriterOptions *options_;

  // Is the builder currently between Finish() and Reset()
  bool finished_;

  // Is this a leaf block?
  bool is_leaf_;

  faststring buffer_;
  std::vector<uint32_t> entry_offsets_;
};

class IndexBlockReader {
 public:
  IndexBlockReader();

  void Reset();

  // Parse the given index block.
  //
  // This function may be called repeatedly to "reset" the reader to process
  // a new block.
  //
  // Note: this does not copy the data, so the slice must
  // remain valid for the lifetime of the reader (or until the next Parse call)
  Status Parse(const Slice &data);

  size_t Count() const;

  IndexBlockIterator *NewIterator() const;

  bool IsLeaf();

 private:
  friend class IndexBlockIterator;

  int CompareKey(int idx_in_block, const Slice &search_key) const;

  Status ReadEntry(size_t idx, Slice *key, BlockPointer *block_ptr) const;

  // Set *ptr to the beginning of the index data for the given index
  // entry.
  // Set *limit to the 'limit' pointer for that entry (i.e a pointer
  // beyond which the data no longer is part of that entry).
  //   - *limit can be used to prevent overrunning in the case of a
  //     corrupted length varint or length prefix
  void GetKeyPointer(int idx_in_block, const uint8_t **ptr, const uint8_t **limit) const;

  static const int kMaxTrailerSize = 64*1024;
  Slice data_;

  IndexBlockTrailerPB trailer_;
  const uint8_t *key_offsets_;
  bool parsed_;

  DISALLOW_COPY_AND_ASSIGN(IndexBlockReader);
};

class IndexBlockIterator {
 public:
  explicit IndexBlockIterator(const IndexBlockReader *reader);

  // Reset the state of this iterator. This should be used
  // after the associated 'reader' object parses a different block.
  void Reset();

  // Find the highest block pointer in this index
  // block which has a value <= the given key.
  // If such a block is found, returns OK status.
  // If no such block is found (i.e the smallest key in the
  // index is still larger than the provided key), then
  // Status::NotFound is returned.
  //
  // If this function returns an error, then the state of this
  // iterator is undefined (i.e it may or may not have moved
  // since the previous call)
  Status SeekAtOrBefore(const Slice &search_key);

  Status SeekToIndex(size_t idx);

  bool HasNext() const;

  Status Next();

  const BlockPointer &GetCurrentBlockPointer() const;

  const Slice GetCurrentKey() const;

 private:
  const IndexBlockReader *reader_;
  size_t cur_idx_;
  Slice cur_key_;
  BlockPointer cur_ptr_;
  bool seeked_;

  DISALLOW_COPY_AND_ASSIGN(IndexBlockIterator);
};

} // namespace cfile
} // namespace kudu
#endif
