/**
 * 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 "storage/TupleStorageSubBlock.hpp"

#include <cassert>

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

namespace quickstep {

tuple_id TupleStorageSubBlock::numTuples() const {
  if (isEmpty()) {
    return 0;
  } else if (isPacked()) {
    return getMaxTupleID() + 1;
  } else {
    // WARNING: This branch is O(N). Subclasses should override wherever possible.
    tuple_id count = 0;
    for (tuple_id tid = 0; tid <= getMaxTupleID(); ++tid) {
      if (hasTupleWithID(tid)) {
        ++count;
      }
    }
    // Should have at least one tuple, otherwise isEmpty() would have been true.
    DEBUG_ASSERT(count > 0);
    return count;
  }
}

TupleIdSequence* TupleStorageSubBlock::getExistenceMap() const {
  const tuple_id max_tid = getMaxTupleID();
  TupleIdSequence *existing_tuples = new TupleIdSequence(max_tid + 1);

  if (isPacked()) {
    existing_tuples->setRange(0, max_tid + 1, true);
  } else {
    for (tuple_id tid = 0; tid <= max_tid; ++tid) {
      if (hasTupleWithID(tid)) {
        existing_tuples->set(tid);
      }
    }
  }

  return existing_tuples;
}

OrderedTupleIdSequence* TupleStorageSubBlock::getExistenceList() const {
  const tuple_id max_tid = getMaxTupleID();
  OrderedTupleIdSequence *existence_list = new OrderedTupleIdSequence();
  existence_list->reserve(numTuples());

  if (isPacked()) {
    for (tuple_id tid = 0; tid <= max_tid; ++tid) {
      existence_list->emplace_back(tid);
    }
  } else {
    for (tuple_id tid = 0; tid <= max_tid; ++tid) {
      if (hasTupleWithID(tid)) {
        existence_list->emplace_back(tid);
      }
    }
  }

  return existence_list;
}

void TupleStorageSubBlock::paranoidInsertTypeCheck(const Tuple &tuple) {
#ifdef QUICKSTEP_DEBUG
  assert(relation_.size() == tuple.size());

  Tuple::const_iterator value_it = tuple.begin();
  CatalogRelationSchema::const_iterator attr_it = relation_.begin();

  while (value_it != tuple.end()) {
    assert(value_it->isPlausibleInstanceOf(attr_it->getType().getSignature()));

    ++value_it;
    ++attr_it;
  }
#endif
}

}  // namespace quickstep
