/**
 * 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 QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_
#define QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_

#include <algorithm>
#include <cstdint>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector>

#include "catalog/CatalogAttribute.hpp"
#include "catalog/CatalogRelationSchema.hpp"
#include "catalog/CatalogTypedefs.hpp"
#include "storage/StorageBlockInfo.hpp"
#include "storage/TupleIdSequence.hpp"
#include "types/TypedValue.hpp"
#include "types/containers/Tuple.hpp"
#include "utility/Macros.hpp"

namespace quickstep {

class TupleStorageSubBlock;

template <bool check_null = true>
class ColumnAccessor;

// TODO(chasseur): Iteration on ValueAccessors is row-at-a-time, but in some
// cases column-wise data movement may be more efficient.

/** \addtogroup Storage
 *  @{
 */

/**
 * @brief Base class for accessors which provide inline-able methods allowing
 *        direct access to attribute values in TupleStorageSubBlocks or
 *        ColumnVectors.
 * @note This base class provides several virtual methods named with the suffix
 *       -Virtual that constitute a common interface that all ValueAccessors
 *       support. Concrete implementation subclasses of ValueAccessor all
 *       provide non-virtual inline versions of these methods without the
 *       -Virtual suffix. The general recommendation is that if client code
 *       only needs to make one or two calls to methods of a ValueAccessor, it
 *       can just use the virtual methods and avoid generating many code
 *       branches for different types of ValueAccessors. If, on the other hand,
 *       methods of a ValueAccessor will be called many times repeatedly (e.g.
 *       in an inner loop), it is recommended to downcast a ValueAccessor to
 *       its concrete type and use the inline methods. The file
 *       ValueAccessorUtil.hpp provides macros to do this automatically.
 **/
class ValueAccessor {
 public:
  /**
   * @brief Enum with cases for different subclasses of ValueAccessor.
   **/
  enum class Implementation {
    // Accessors for values inside a TupleStorageSubBlock:
    kBasicColumnStore,
    kCompressedColumnStore,
    kCompressedPackedRowStore,
    kSplitRowStore,
    // Accessor for a group of ColumnVectors:
    kColumnVectors
  };

  ValueAccessor() {
  }

  virtual ~ValueAccessor() {
  }

  /**
   * @brief Determine the concrete type of this ValueAccessor.
   * @note See also isTupleIdSequenceAdapter() and
   *       isOrderedTupleIdSequenceAdapter(), which check if a templated
   *       adapter is being used.
   *
   * @return The implementation type of this ValueAccessor.
   **/
  virtual Implementation getImplementationType() const = 0;

  /**
   * @brief Determine if this ValueAccessor is a
   *        TupleIdSequenceAdapterValueAccessor.
   *
   * @return true if this is a TupleIdSequenceAdapterValueAccessor, false
   *         otherwise.
   **/
  virtual bool isTupleIdSequenceAdapter() const = 0;

  /**
   * @brief Determine if this ValueAccessor is an
   *        OrderedTupleIdSequenceAdapterValueAccessor.
   *
   * @return true if thhis is an OrderedTupleIdSequenceAdapterValueAccessor,
   *         false otherwise.
   **/
  virtual bool isOrderedTupleIdSequenceAdapter() const = 0;

  /**
   * @brief Start statefully iterating over tuples from this ValueAccessor.
   * @note Conceptually, this method sets the "position" of the ValueAccessor
   *       to one-before the start of tuples. nextVirtual()/next() should be
   *       called before attempting to read values.
   **/
  virtual void beginIterationVirtual() = 0;

  /**
   * @brief Determine whether the stateful iteration over tuples in this
   *        ValueAccessor is finished (i.e. there are no more tuples to iterate
   *        over).
   *
   * @return true if iteration is finished (i.e. a subsequent call to
   *         nextVirtual()/next() will return false). Note that this returns
   *         true if iteration is past-the-end of tuples OR on the very last
   *         tuple.
   **/
  virtual bool iterationFinishedVirtual() const = 0;

  /**
   * @brief Advance stateful iteration to the next tuple from this
   *        ValueAccessor.
   *
   * @return true if advanced to another tuple, false if there are no more
   *         tuples.
   **/
  virtual bool nextVirtual() = 0;

  /**
   * @brief Rewind stateful iteration by one tuple (i.e. undo the last call to
   *        nextVirtual()/next()).
   **/
  virtual void previousVirtual() = 0;

  /**
   * @brief Get the current absolute position of stateful iteration on this
   *        ValueAccessor (i.e. the tuple_id of the corresponding tuple in a
   *        TupleStorageSubBlock).
   *
   * @return The absolute position of the current tuple in stateful iteration.
   **/
  virtual tuple_id getCurrentPositionVirtual() const = 0;

  /**
   * @brief Get the "end" absolute position of tuples accessible via this
   *        ValueAccessor (i.e. the absolute position of the last tuple plus
   *        one).
   *
   * @return The end position of tuples accessible via this ValueAccessor.
   **/
  virtual tuple_id getEndPositionVirtual() const = 0;

  /**
   * @brief Get the actual number of tuples accessible via this ValueAccessor.
   * @note This is different from getEndPositionVirtual()/getEndPosition(),
   *       because there may be gaps in the sequence of tuple positions that a
   *       ValueAccessor iterates over (e.g. because a
   *       TupleIdSequenceAdapterValueAccessor is being used, or because the
   *       base TupleStorageSubBlock (e.g. SplitRowStoreTupleStorageSubBlock)
   *       allows empty tuple slots).
   *
   * @return The actual number of tuples accessible via this ValueAccessor.
   **/
  virtual tuple_id getNumTuplesVirtual() const = 0;

  /**
   * @brief Returns whether this accessor has a fast strided ColumnAccessor available
   *        that can be used to optimize memory access in a tight loop iteration
   *        over the underlying storage block. Specific derived classes should override
   *        this method if they support ColumnAccessor.
   *
   * @return true if fast ColumnAccessor is supported, otherwise false.
   */
  virtual inline bool isColumnAccessorSupported() const {
    return false;
  }

  /**
   * @brief Get a pointer to an untyped value for the current tuple in stateful
   *        iteration.
   * @note The inline version of this method provided by subclasses,
   *       getUntypedValue(), takes an optional bool template parameter
   *       indicating whether checks for null-values should be performed. If it
   *       is known that the Type for an attribute is not nullable, using false
   *       for that template parameter may result in a faster version of the
   *       method that avoids a branch to check for nulls.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get
   *        from the current tuple.
   * @return An untyped pointer to the attribute value specified by attr_id for
   *         the current tuple.
   **/
  virtual const void* getUntypedValueVirtual(const attribute_id attr_id) const = 0;

  /**
   * @brief Get a TypedValue for the current tuple in stateful iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get
   *        from the current tuple.
   * @return The attribute value specified by attr_id for the current tuple.
   **/
  virtual TypedValue getTypedValueVirtual(const attribute_id attr_id) const = 0;

  /**
   * @brief Get a pointer to an untyped value for the tuple at an explicitly
   *        specified absolute position.
   * @note The inline version of this method provided by subclasses,
   *       getUntypedValueAtAbsolutePosition(), takes an optional bool template
   *       parameter indicating whether checks for null-values should be
   *       performed. If it is known that the Type for an attribute is not
   *       nullable, using false for that template parameter may result in a
   *       faster version of the method that avoids a branch to check for
   *       nulls.
   * @warning It is the caller's responsbility to ensure that there actually is
   *          a tuple at the specified position.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get.
   * @param tid The absolute position of the tuple to get a value from.
   * @return An untyped pointer to the attribute value specified by attr_id in
   *         the tuple at the position specified by tid.
   **/
  virtual const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const = 0;

  /**
   * @brief Get a TypedValue for the tuple at an explicitly specified absolute
   *        position.
   * @warning It is the caller's responsbility to ensure that there actually is
   *          a tuple at the specified position.
   *
   * @param attr_id The attribute_id indicating which attribute's value to get.
   * @param tid The absolute position of the tuple to get a value from.
   * @return The attribute value specified by attr_id in the tuple at the
   *         position specified by tid.
   **/
  virtual TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const = 0;

  /**
   * @brief Create a Tuple object containing all the attribute values for the
   *        current tuple in stateful iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @return A new Tuple object (caller takes ownership) containing all the
   *         attribute values for the current tuple in stateful iteration.
   **/
  virtual Tuple* getTupleVirtual() const = 0;

  /**
   * @brief Create a Tuple object containing values of explicitly-specified
   *        attributes in a specified order for the current tuple in stateful
   *        iteration.
   * @warning This method should only be called if the previous call to
   *          nextVirtual()/next() return true.
   *
   * @param attributes The IDs of attributes, in the desired order, to fill
   *        the returned Tuple with.
   * @return A new Tuple object (caller takes ownership) containing the
   *         specified attribute values for the current tuple in stateful
   *         iteration.
   **/
  virtual Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const = 0;

  /**
   * @brief Create a new TupleIdSequenceAdapterValueAccessor that wraps this
   *        ValueAccessor.
   * @warning The newly-created adapter does NOT take ownership of this
   *          ValueAccessor nor the provided TupleIdSequence. Both must remain
   *          valid so long as the adapter will be used.
   *
   * @param id_sequence A TupleIdSequence specifying some subset of the tuples
   *        for this ValueAccessor that the adapter will iterate over.
   * @return A new TupleIdSequenceAdapterValueAccessor that will iterate over
   *         only the tuples specified in id_sequence.
   **/
  virtual ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) = 0;

  /**
   * @brief Create a new OrderedTupleIdSequenceAdapterValueAccessor that wraps
   *        this ValueAccessor.
   * @warning The newly-created adapter does NOT take ownership of this
   *          ValueAccessor nor the provided OrderedTupleIdSequence. Both must
   *          remain valid so long as the adapter will be used.
   *
   * @param id_sequence An OrderedTupleIdSequence specifying some subset of the
   *        tuples for this ValueAccessor that the adapter will iterate over.
   * @return A new OrderedTupleIdSequenceAdapterValueAccessor that will iterate
   *         over only the tuples specified in id_sequence.
   **/
  virtual ValueAccessor* createSharedOrderedTupleIdSequenceAdapterVirtual(
      const OrderedTupleIdSequence &id_sequence) = 0;

  /**
   * @brief Get a TupleIdSequence indicating which positions this ValueAccessor
   *        is iterating over.
   *
   * @return A pointer to a TupleIdSequence that indicates which absolute
   *         positions this ValueAccessor iterates over. Returns NULL if there
   *         are no gaps in the iteration sequence (i.e. iteration goes from
   *         position 0 to getEndPositionVirtual() - 1 without skipping
   *         anything).
   **/
  virtual const TupleIdSequence* getTupleIdSequenceVirtual() const = 0;

 private:
  DISALLOW_COPY_AND_ASSIGN(ValueAccessor);
};

template <typename InternalValueAccessorType>
class OrderedTupleIdSequenceAdapterValueAccessor;

/**
 * @brief Adapter for another ValueAccessor which only iterates over tuples in
 *        a TupleIdSequence.
 **/
template <typename InternalValueAccessorType>
class TupleIdSequenceAdapterValueAccessor : public ValueAccessor {
 public:
  TupleIdSequenceAdapterValueAccessor(InternalValueAccessorType *accessor,
                                      const TupleIdSequence &id_sequence,
                                      const bool take_ownership_of_accessor = true)
      : accessor_(accessor),
        owned_accessor_(take_ownership_of_accessor ? accessor : nullptr),
        id_sequence_(id_sequence),
        current_position_(id_sequence.before_begin()) {
  }

  ~TupleIdSequenceAdapterValueAccessor() override {
  }

  Implementation getImplementationType() const override {
    return accessor_->getImplementationType();
  }

  bool isTupleIdSequenceAdapter() const override {
    return true;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return false;
  }

  inline void beginIteration() {
    current_position_ = id_sequence_.before_begin();
  }

  inline bool iterationFinished() const {
    TupleIdSequence::const_iterator next_position = current_position_;
    ++next_position;
    return (current_position_ == id_sequence_.end())
           || (next_position == id_sequence_.end());
  }

  inline bool next() {
    ++current_position_;
    return current_position_ != id_sequence_.end();
  }

  inline void previous() {
    --current_position_;
  }

  inline tuple_id getCurrentPosition() const {
    return *current_position_;
  }

  inline tuple_id getEndPosition() const {
    return id_sequence_.length();
  }

  inline tuple_id getNumTuples() const {
    return id_sequence_.numTuples();
  }

  /**
   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
   *        access on the underlying storage block.
   * @note The ownership of the returned object lies with the caller.
   * @warning This method should only be called if isColumnAccessorSupported() method
   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
   *
   * @param attr_id The attribute id on which this ColumnAccessor will be created.
   *
   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
   *         in a tight loop iterations over the underlying storage block.
   **/
  template <bool check_null = true>
  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
    // Column Accessors are currently unsupported for this accessor, hence nullptr.
    return nullptr;
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id, *current_position_);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, *current_position_);
  }

  // Pass-through.
  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id, tid);
  }

  // Pass-through.
  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  inline Tuple* getTuple() const {
    return accessor_->getTupleAtAbsolutePosition(*current_position_);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return accessor_->getTupleAtAbsolutePositionWithAttributes(*current_position_, attributes);
  }

  inline TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType> *createSharedTupleIdSequenceAdapter(
      const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>
      *createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    return &id_sequence_;
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  ValueAccessor* createSharedOrderedTupleIdSequenceAdapterVirtual(
      const OrderedTupleIdSequence &id_sequence) override {
    return createSharedOrderedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  InternalValueAccessorType *accessor_;
  std::unique_ptr<InternalValueAccessorType> owned_accessor_;
  const TupleIdSequence &id_sequence_;
  TupleIdSequence::const_iterator current_position_;

  DISALLOW_COPY_AND_ASSIGN(TupleIdSequenceAdapterValueAccessor);
};

/**
 * @brief Adapter for another ValueAccessor which only iterates over tuples in
 *        an OrderedTupleIdSequence.
 **/
template <typename InternalValueAccessorType>
class OrderedTupleIdSequenceAdapterValueAccessor : public ValueAccessor {
 public:
  OrderedTupleIdSequenceAdapterValueAccessor(InternalValueAccessorType *accessor,
                                             const OrderedTupleIdSequence &id_sequence,
                                             const bool take_ownership_of_accessor = true)
      : accessor_(accessor),
        owned_accessor_(take_ownership_of_accessor ? accessor : nullptr),
        id_sequence_(id_sequence),
        current_position_(std::numeric_limits<OrderedTupleIdSequence::size_type>::max()) {
    static_assert(std::numeric_limits<OrderedTupleIdSequence::size_type>::is_modulo,
                  "size_type does not support modulo overflow.");
  }

  ~OrderedTupleIdSequenceAdapterValueAccessor() {
  }

  Implementation getImplementationType() const override {
    return accessor_->getImplementationType();
  }

  bool isTupleIdSequenceAdapter() const override {
    return false;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return true;
  }

  inline void beginIteration() {
    current_position_ = std::numeric_limits<OrderedTupleIdSequence::size_type>::max();
  }

  inline bool iterationFinished() const {
    return current_position_ + 1 >= id_sequence_.size();
  }

  inline bool next() {
    ++current_position_;
    return current_position_ != id_sequence_.size();
  }

  inline void previous() {
    --current_position_;
  }

  inline tuple_id getCurrentPosition() const {
    return id_sequence_[current_position_];
  }

  inline tuple_id getEndPosition() const {
    OrderedTupleIdSequence::const_iterator max_it = std::max_element(id_sequence_.begin(), id_sequence_.end());
    return (max_it != id_sequence_.end() ? *max_it : 0) + 1;
  }

  inline tuple_id getNumTuples() const {
    return id_sequence_.size();
  }

  /**
   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
   *        access on the underlying storage block.
   * @note The ownership of the returned object lies with the caller.
   * @warning This method should only be called if isColumnAccessorSupported() method
   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
   *
   * @param attr_id The attribute id on which this ColumnAccessor will be created.
   *
   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
   *         in a tight loop iterations over the underlying storage block.
   **/
  template <bool check_null = true>
  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
    // Column Accessors are currently unsupported for this accessor, hence nullptr.
    return nullptr;
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return accessor_->template getUntypedValueAtAbsolutePosition<check_null>(attr_id,
                                                                             id_sequence_[current_position_]);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return accessor_->getTypedValueAtAbsolutePosition(attr_id, id_sequence_[current_position_]);
  }

  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    FATAL_ERROR("getUntypedValueAtAbsolutePosition() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    FATAL_ERROR("getTypedValueAtAbsolutePosition() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  inline Tuple* getTuple() const {
    return accessor_->getTupleAtAbsolutePosition(id_sequence_[current_position_]);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return accessor_->getTupleAtAbsolutePositionWithAttributes(id_sequence_[current_position_], attributes);
  }

  inline TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>*
      createSharedTupleIdSequenceAdapter(const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_,
                                                                              id_sequence,
                                                                              false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>
      *createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<InternalValueAccessorType>(accessor_, id_sequence, false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    FATAL_ERROR("getTupleIdSequence() not implemented in "
                "OrderedTupleIdSequenceAdapterValueAccessor");
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  ValueAccessor* createSharedOrderedTupleIdSequenceAdapterVirtual(
      const OrderedTupleIdSequence &id_sequence) override {
    return createSharedOrderedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  InternalValueAccessorType *accessor_;
  std::unique_ptr<InternalValueAccessorType> owned_accessor_;
  const OrderedTupleIdSequence &id_sequence_;
  OrderedTupleIdSequence::size_type current_position_;

  DISALLOW_COPY_AND_ASSIGN(OrderedTupleIdSequenceAdapterValueAccessor);
};

/**
 * @brief Templated implementation of ValueAccessor for any packed
 *        TupleStorageSubBlock.
 **/
template <typename TupleStorageSubBlockT,
          typename HelperT,
          ValueAccessor::Implementation impl_type>
class PackedTupleStorageSubBlockValueAccessor : public ValueAccessor {
 public:
  ~PackedTupleStorageSubBlockValueAccessor() override {
  }

  Implementation getImplementationType() const override {
    return impl_type;
  }

  bool isTupleIdSequenceAdapter() const override {
    return false;
  }

  bool isOrderedTupleIdSequenceAdapter() const override {
    return false;
  }

  inline void beginIteration() {
    current_tuple_ = -1;
  }

  inline bool iterationFinished() const {
    return current_tuple_ + 1 >= helper_.numPackedTuples();
  }

  inline bool next() {
    ++current_tuple_;
    return (current_tuple_ < helper_.numPackedTuples());
  }

  inline void previous() {
    --current_tuple_;
  }

  inline tuple_id getCurrentPosition() const {
    return current_tuple_;
  }

  inline tuple_id getEndPosition() const {
    return helper_.numPackedTuples();
  }

  inline tuple_id getNumTuples() const {
    return helper_.numPackedTuples();
  }

  template <bool check_null = true>
  inline const void* getUntypedValue(const attribute_id attr_id) const {
    return getUntypedValueAtAbsolutePosition<check_null>(attr_id, current_tuple_);
  }

  inline TypedValue getTypedValue(const attribute_id attr_id) const {
    return getTypedValueAtAbsolutePosition(attr_id, current_tuple_);
  }

  inline bool isColumnAccessorSupported() const override {
    return helper_.isColumnAccessorSupported();
  }

  /**
   * @brief Get a pointer to a ColumnAccessor object that provides a fast strided memory
   *        access on the underlying storage block.
   * @note The ownership of the returned object lies with the caller.
   * @warning This method should only be called if isColumnAccessorSupported() method
   *          returned true. If ColumnAccessor is not supported this method will return a nullptr.
   *
   * @param attr_id The attribute id on which this ColumnAccessor will be created.
   *
   * @return A pointer to a ColumnAccessor object with specific properties set that can be used
   *         in a tight loop iterations over the underlying storage block.
   **/
  template <bool check_null = true>
  inline const ColumnAccessor<check_null>* getColumnAccessor(const attribute_id attr_id) const {
    return helper_.template getColumnAccessor<check_null>(current_tuple_, attr_id);
  }

  template <bool check_null = true>
  inline const void* getUntypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                       const tuple_id tid) const {
    return helper_.template getAttributeValue<check_null>(tid, attr_id);
  }

  inline TypedValue getTypedValueAtAbsolutePosition(const attribute_id attr_id,
                                                    const tuple_id tid) const {
    return helper_.getAttributeValueTyped(tid, attr_id);
  }

  inline Tuple* getTuple() const {
    return getTupleAtAbsolutePosition(current_tuple_);
  }

  inline Tuple* getTupleWithAttributes(const std::vector<attribute_id> &attributes) const {
    return getTupleAtAbsolutePositionWithAttributes(current_tuple_, attributes);
  }

  inline Tuple* getTupleAtAbsolutePosition(const tuple_id tid) const {
    std::vector<TypedValue> values;
    if (relation_.gapsInAttributeSequence()) {
      for (const CatalogAttribute &attr : relation_) {
        values.emplace_back(getTypedValueAtAbsolutePosition(attr.getID(), tid));
      }
    } else {
      const attribute_id max_attr_id = relation_.getMaxAttributeId();
      for (attribute_id attr_id = 0;
           attr_id <= max_attr_id;
           ++attr_id) {
        values.emplace_back(getTypedValueAtAbsolutePosition(attr_id, tid));
      }
    }
    return new Tuple(std::move(values));
  }

  inline Tuple* getTupleAtAbsolutePositionWithAttributes(
      const tuple_id tid,
      const std::vector<attribute_id> &attributes) const {
    std::vector<TypedValue> values;
    for (const attribute_id attr_id : attributes) {
      values.emplace_back(getTypedValueAtAbsolutePosition(attr_id, tid));
    }
    return new Tuple(std::move(values));
  }

  inline TupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>*
      createSharedTupleIdSequenceAdapter(const TupleIdSequence &id_sequence) {
    return new TupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>(
        this,
        id_sequence,
        false);
  }

  inline OrderedTupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>*
      createSharedOrderedTupleIdSequenceAdapter(const OrderedTupleIdSequence &id_sequence) {
    return new OrderedTupleIdSequenceAdapterValueAccessor<PackedTupleStorageSubBlockValueAccessor>(
        this,
        id_sequence,
        false);
  }

  inline const TupleIdSequence* getTupleIdSequence() const {
    return nullptr;
  }

  // Implementation of virtuals that pass-through to the inline
  // implementations.
  void beginIterationVirtual() override {
    beginIteration();
  }

  bool iterationFinishedVirtual() const override {
    return iterationFinished();
  }

  bool nextVirtual() override {
    return next();
  }

  void previousVirtual() override {
    previous();
  }

  tuple_id getCurrentPositionVirtual() const override {
    return getCurrentPosition();
  }

  tuple_id getEndPositionVirtual() const override {
    return getEndPosition();
  }

  tuple_id getNumTuplesVirtual() const override {
    return getNumTuples();
  }

  const void* getUntypedValueVirtual(const attribute_id attr_id) const override {
    return getUntypedValue(attr_id);
  }

  TypedValue getTypedValueVirtual(const attribute_id attr_id) const override {
    return getTypedValue(attr_id);
  }

  const void* getUntypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getUntypedValueAtAbsolutePosition(attr_id, tid);
  }

  TypedValue getTypedValueAtAbsolutePositionVirtual(
      const attribute_id attr_id,
      const tuple_id tid) const override {
    return getTypedValueAtAbsolutePosition(attr_id, tid);
  }

  Tuple* getTupleVirtual() const override {
    return getTuple();
  }

  Tuple* getTupleWithAttributesVirtual(
      const std::vector<attribute_id> &attributes) const override {
    return getTupleWithAttributes(attributes);
  }

  ValueAccessor* createSharedTupleIdSequenceAdapterVirtual(
      const TupleIdSequence &id_sequence) override {
    return createSharedTupleIdSequenceAdapter(id_sequence);
  }

  ValueAccessor* createSharedOrderedTupleIdSequenceAdapterVirtual(
      const OrderedTupleIdSequence &id_sequence) override {
    return createSharedOrderedTupleIdSequenceAdapter(id_sequence);
  }

  const TupleIdSequence* getTupleIdSequenceVirtual() const override {
    return getTupleIdSequence();
  }

 private:
  template <typename... HelperArgs>
  PackedTupleStorageSubBlockValueAccessor(
      const CatalogRelationSchema &relation,
      HelperArgs&&... helper_args)
      : relation_(relation),
        helper_(std::forward<HelperArgs>(helper_args)...),
        current_tuple_(-1) {
  }

  const CatalogRelationSchema &relation_;
  HelperT helper_;
  tuple_id current_tuple_;

  friend TupleStorageSubBlockT;

  DISALLOW_COPY_AND_ASSIGN(PackedTupleStorageSubBlockValueAccessor);
};


/**
 * @brief ColumnAccessor is a helper template class that is used to optimize memory
 *        access patterns for a ValueAccessor when it is used in a tight loop
 *        to extract values for a given attribute from a given storage block.
 **/
template <bool check_null>
class ColumnAccessor {
 public:
  /**
   * @brief Constructor.
   *
   * @param current_tuple_position A constant reference to the tuple position in the containing
   *        ValueAccessor. This reference value is shared between the containing ValueAccessor &
   *        a ColumnAccessor. However, a ColumnAccessor *CANNOT* modify this tuple position.
   * @param num_tuples Number of tuples for this block.
   * @param base_address The starting address in memory for the first column value.
   * @param stride The memory offset at which other column values will be found.
   * @param null_bitmap The bitmap that will be referred in case of nullable attributes.
   * @param nullable_base The starting index for the first nullable attribute in the bitmap.
   *        Note that setting this value to -1 will essentially cause null checks to always
   *        return false.
   * @param nullable_stride The offset at which null bits will be found for
   *        different attribute values.
   **/
  ColumnAccessor(const tuple_id &current_tuple_position,
                 const std::size_t num_tuples,
                 const void *base_address,
                 const std::size_t stride,
                 const BitVector<false> *null_bitmap = nullptr,
                 const int nullable_base = -1,
                 const unsigned nullable_stride = 0)
      : current_tuple_position_(current_tuple_position),
        num_tuples_(num_tuples),
        base_address_(base_address),
        stride_(stride),
        null_bitmap_(null_bitmap),
        nullable_base_(nullable_base),
        nullable_stride_(nullable_stride) {
  }

  /**
   * @brief Get a pointer to an untyped value for the current tuple in stateful
   *        iteration over the given column.
   *
   * @return An untyped pointer to the attribute value for the current tuple.
   **/
  inline const void* getUntypedValue() const {
    DCHECK(current_tuple_position_ < num_tuples_);
    if (check_null) {
      DCHECK(null_bitmap_ != nullptr);
      if ((nullable_base_ != -1)
          && null_bitmap_->getBit(current_tuple_position_ * nullable_stride_ + nullable_base_)) {
        return nullptr;
      }
    }
    return static_cast<const char*>(base_address_) + current_tuple_position_ * stride_;
  }

 private:
  const tuple_id &current_tuple_position_;
  const tuple_id num_tuples_;
  const void *base_address_;
  const std::size_t stride_;
  const BitVector<false> *null_bitmap_;
  const int nullable_base_;
  const unsigned nullable_stride_;

  DISALLOW_COPY_AND_ASSIGN(ColumnAccessor);
};

/** @} */

}  // namespace quickstep

#endif  // QUICKSTEP_STORAGE_VALUE_ACCESSOR_HPP_
