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

namespace red_arrow {
  namespace {
    class ValuesBuilder : private Converter, public arrow::ArrayVisitor {
    public:
      explicit ValuesBuilder(VALUE values)
        : Converter(),
          values_(values),
          row_offset_(0) {
      }

      void build(const arrow::Array& array, VALUE rb_array) {
        rb::protect([&] {
          check_status(array.Accept(this),
                       "[array][values]");
          return Qnil;
        });
      }

      void build(const arrow::ChunkedArray& chunked_array,
                 VALUE rb_chunked_array) {
        rb::protect([&] {
          for (const auto& array : chunked_array.chunks()) {
            check_status(array->Accept(this),
                         "[chunked-array][values]");
            row_offset_ += array->length();
          }
          return Qnil;
        });
      }

#define VISIT(TYPE)                                                     \
      arrow::Status Visit(const arrow::TYPE ## Array& array) override { \
        convert(array);                                                 \
        return arrow::Status::OK();                                     \
      }

      VISIT(Null)
      VISIT(Boolean)
      VISIT(Int8)
      VISIT(Int16)
      VISIT(Int32)
      VISIT(Int64)
      VISIT(UInt8)
      VISIT(UInt16)
      VISIT(UInt32)
      VISIT(UInt64)
      // TODO
      // VISIT(HalfFloat)
      VISIT(Float)
      VISIT(Double)
      VISIT(Binary)
      VISIT(String)
      VISIT(FixedSizeBinary)
      VISIT(Date32)
      VISIT(Date64)
      VISIT(Time32)
      VISIT(Time64)
      VISIT(Timestamp)
      // TODO
      // VISIT(Interval)
      VISIT(List)
      VISIT(Struct)
      VISIT(SparseUnion)
      VISIT(DenseUnion)
      VISIT(Dictionary)
      VISIT(Decimal128)
      VISIT(Decimal256)
      // TODO
      // VISIT(Extension)

#undef VISIT

    private:
      template <typename ArrayType>
      void convert(const ArrayType& array) {
        const auto n = array.length();
        if (array.null_count() > 0) {
          for (int64_t i = 0, ii = row_offset_; i < n; ++i, ++ii) {
            auto value = Qnil;
            if (!array.IsNull(i)) {
              value = convert_value(array, i);
            }
            rb_ary_store(values_, ii, value);
          }
        } else {
          for (int64_t i = 0, ii = row_offset_; i < n; ++i, ++ii) {
            rb_ary_store(values_, ii, convert_value(array, i));
          }
        }
      }

      // Destination for converted values.
      VALUE values_;

      // The current row offset.
      int64_t row_offset_;
    };
  }

  VALUE
  array_values(VALUE rb_array) {
    auto garrow_array = GARROW_ARRAY(RVAL2GOBJ(rb_array));
    auto array = garrow_array_get_raw(garrow_array).get();
    const auto n_rows = array->length();
    auto values = rb_ary_new_capa(n_rows);

    try {
      ValuesBuilder builder(values);
      builder.build(*array, rb_array);
    } catch (rb::State& state) {
      state.jump();
    }

    return values;
  }

  VALUE
  chunked_array_values(VALUE rb_chunked_array) {
    auto garrow_chunked_array =
      GARROW_CHUNKED_ARRAY(RVAL2GOBJ(rb_chunked_array));
    auto chunked_array =
      garrow_chunked_array_get_raw(garrow_chunked_array).get();
    const auto n_rows = chunked_array->length();
    auto values = rb_ary_new_capa(n_rows);

    try {
      ValuesBuilder builder(values);
      builder.build(*chunked_array, rb_chunked_array);
    } catch (rb::State& state) {
      state.jump();
    }

    return values;
  }
}
