// 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 "parquet/column_scanner.h"

#include <cstdint>
#include <memory>

#include "parquet/column_reader.h"
#include "parquet/util/memory.h"

using arrow::MemoryPool;

namespace parquet {

std::shared_ptr<Scanner> Scanner::Make(std::shared_ptr<ColumnReader> col_reader,
                                       int64_t batch_size, MemoryPool* pool) {
  switch (col_reader->type()) {
    case Type::BOOLEAN:
      return std::make_shared<BoolScanner>(col_reader, batch_size, pool);
    case Type::INT32:
      return std::make_shared<Int32Scanner>(col_reader, batch_size, pool);
    case Type::INT64:
      return std::make_shared<Int64Scanner>(col_reader, batch_size, pool);
    case Type::INT96:
      return std::make_shared<Int96Scanner>(col_reader, batch_size, pool);
    case Type::FLOAT:
      return std::make_shared<FloatScanner>(col_reader, batch_size, pool);
    case Type::DOUBLE:
      return std::make_shared<DoubleScanner>(col_reader, batch_size, pool);
    case Type::BYTE_ARRAY:
      return std::make_shared<ByteArrayScanner>(col_reader, batch_size, pool);
    case Type::FIXED_LEN_BYTE_ARRAY:
      return std::make_shared<FixedLenByteArrayScanner>(col_reader, batch_size, pool);
    default:
      ParquetException::NYI("type reader not implemented");
  }
  // Unreachable code, but supress compiler warning
  return std::shared_ptr<Scanner>(nullptr);
}

int64_t ScanAllValues(int32_t batch_size, int16_t* def_levels, int16_t* rep_levels,
                      uint8_t* values, int64_t* values_buffered,
                      parquet::ColumnReader* reader) {
  switch (reader->type()) {
    case parquet::Type::BOOLEAN:
      return ScanAll<parquet::BoolReader>(batch_size, def_levels, rep_levels, values,
                                          values_buffered, reader);
    case parquet::Type::INT32:
      return ScanAll<parquet::Int32Reader>(batch_size, def_levels, rep_levels, values,
                                           values_buffered, reader);
    case parquet::Type::INT64:
      return ScanAll<parquet::Int64Reader>(batch_size, def_levels, rep_levels, values,
                                           values_buffered, reader);
    case parquet::Type::INT96:
      return ScanAll<parquet::Int96Reader>(batch_size, def_levels, rep_levels, values,
                                           values_buffered, reader);
    case parquet::Type::FLOAT:
      return ScanAll<parquet::FloatReader>(batch_size, def_levels, rep_levels, values,
                                           values_buffered, reader);
    case parquet::Type::DOUBLE:
      return ScanAll<parquet::DoubleReader>(batch_size, def_levels, rep_levels, values,
                                            values_buffered, reader);
    case parquet::Type::BYTE_ARRAY:
      return ScanAll<parquet::ByteArrayReader>(batch_size, def_levels, rep_levels, values,
                                               values_buffered, reader);
    case parquet::Type::FIXED_LEN_BYTE_ARRAY:
      return ScanAll<parquet::FixedLenByteArrayReader>(batch_size, def_levels, rep_levels,
                                                       values, values_buffered, reader);
    default:
      parquet::ParquetException::NYI("type reader not implemented");
  }
  // Unreachable code, but supress compiler warning
  return 0;
}

}  // namespace parquet
