/*
 * 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 "paimon/common/data/columnar/columnar_array.h"

#include <utility>

#include "arrow/api.h"
#include "arrow/array/array_decimal.h"
#include "arrow/array/array_nested.h"
#include "arrow/array/array_primitive.h"
#include "arrow/type_traits.h"
#include "arrow/util/decimal.h"
#include "fmt/format.h"
#include "paimon/common/data/columnar/columnar_batch_context.h"
#include "paimon/common/data/columnar/columnar_map.h"
#include "paimon/common/data/columnar/columnar_row_ref.h"
#include "paimon/common/utils/checked_cast.h"
#include "paimon/common/utils/date_time_utils.h"

namespace paimon {
Status ColumnarArray::CheckNoNull() const {
    for (int32_t i = 0; i < length_; i++) {
        if (IsNullAt(i)) {
            return Status::Invalid(fmt::format("row {} is null", i));
        }
    }
    return Status::OK();
}

Decimal ColumnarArray::GetDecimal(int32_t pos, int32_t precision, int32_t scale) const {
    using ArrayType = typename arrow::TypeTraits<arrow::Decimal128Type>::ArrayType;
    auto array = checked_cast<const ArrayType*>(array_);
    arrow::Decimal128 decimal(array->GetValue(offset_ + pos));
    return Decimal(
        precision, scale,
        static_cast<Decimal::int128_t>(
            static_cast<Decimal::uint128_t>(static_cast<uint64_t>(decimal.high_bits())) << 64 |
            decimal.low_bits()));
}

Timestamp ColumnarArray::GetTimestamp(int32_t pos, int32_t precision) const {
    using ArrayType = typename arrow::TypeTraits<arrow::TimestampType>::ArrayType;
    auto array = checked_cast<const ArrayType*>(array_);
    int64_t data = array->Value(offset_ + pos);
    auto timestamp_type = checked_pointer_cast<arrow::TimestampType>(array->type());
    // for orc format, data is saved as nano, therefore, Timestamp convert should consider precision
    // in arrow array rather than input precision
    DateTimeUtils::TimeType time_type = DateTimeUtils::GetTimeTypeFromArrowType(timestamp_type);
    auto [milli, nano] = DateTimeUtils::TimestampConverter(
        data, time_type, DateTimeUtils::TimeType::MILLISECOND, DateTimeUtils::TimeType::NANOSECOND);
    return Timestamp(milli, nano);
}

std::shared_ptr<InternalArray> ColumnarArray::GetArray(int32_t pos) const {
    auto list_array = checked_cast<const arrow::ListArray*>(array_);
    int32_t offset = list_array->value_offset(offset_ + pos);
    int32_t length = list_array->value_length(offset_ + pos);
    return std::make_shared<ColumnarArray>(list_array->values().get(), pool_, offset, length);
}

std::shared_ptr<InternalMap> ColumnarArray::GetMap(int32_t pos) const {
    auto map_array = checked_cast<const arrow::MapArray*>(array_);
    int32_t offset = map_array->value_offset(offset_ + pos);
    int32_t length = map_array->value_length(offset_ + pos);
    return std::make_shared<ColumnarMap>(map_array->keys(), map_array->items(), pool_, offset,
                                         length);
}

std::shared_ptr<InternalRow> ColumnarArray::GetRow(int32_t pos, int32_t num_fields) const {
    auto struct_array = checked_cast<const arrow::StructArray*>(array_);
    auto row_ctx = std::make_shared<ColumnarBatchContext>(struct_array->fields(), pool_);
    return std::make_shared<ColumnarRowRef>(std::move(row_ctx), offset_ + pos);
}

Result<std::vector<char>> ColumnarArray::ToBooleanArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<char> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        bool element = GetBoolean(i);
        res[i] = element ? static_cast<char>(1) : static_cast<char>(0);
    }
    return res;
}

Result<std::vector<char>> ColumnarArray::ToByteArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<char> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetByte(i);
    }
    return res;
}

Result<std::vector<int16_t>> ColumnarArray::ToShortArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<int16_t> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetShort(i);
    }
    return res;
}

Result<std::vector<int32_t>> ColumnarArray::ToIntArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<int32_t> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetInt(i);
    }
    return res;
}

Result<std::vector<int64_t>> ColumnarArray::ToLongArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<int64_t> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetLong(i);
    }
    return res;
}

Result<std::vector<float>> ColumnarArray::ToFloatArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<float> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetFloat(i);
    }
    return res;
}

Result<std::vector<double>> ColumnarArray::ToDoubleArray() const {
    PAIMON_RETURN_NOT_OK(CheckNoNull());
    std::vector<double> res(length_);
    for (int32_t i = 0; i < length_; i++) {
        res[i] = GetDouble(i);
    }
    return res;
}

}  // namespace paimon
