/*
 * 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/serializer/binary_serializer_utils.h"

#include "paimon/common/data/binary_array_writer.h"
#include "paimon/common/data/binary_row_writer.h"
#include "paimon/common/utils/date_time_utils.h"
namespace paimon {
Result<std::shared_ptr<BinaryArray>> BinarySerializerUtils::WriteBinaryArray(
    const std::shared_ptr<InternalArray>& value, const std::shared_ptr<arrow::DataType>& type,
    MemoryPool* pool) {
    if (auto binary_array = std::dynamic_pointer_cast<BinaryArray>(value)) {
        return binary_array;
    }
    auto binary_array = std::make_shared<BinaryArray>();
    auto list_type = std::dynamic_pointer_cast<arrow::ListType>(type);
    assert(list_type);
    auto value_type = list_type->value_type();
    // TODO(xinyu.lxy): reuse BinaryWriter
    BinaryArrayWriter binary_writer(binary_array.get(), value->Size(),
                                    BinaryArrayWriter::GetElementSize(value_type->id()), pool);
    for (int32_t i = 0; i < value->Size(); i++) {
        PAIMON_RETURN_NOT_OK(WriteBinaryData(value_type, value.get(), i, &binary_writer, pool));
    }
    binary_writer.Complete();
    return binary_array;
}

Result<std::shared_ptr<BinaryMap>> BinarySerializerUtils::WriteBinaryMap(
    const std::shared_ptr<InternalMap>& value, const std::shared_ptr<arrow::DataType>& type,
    MemoryPool* pool) {
    if (auto binary_map = std::dynamic_pointer_cast<BinaryMap>(value)) {
        return binary_map;
    }
    auto map_type = std::dynamic_pointer_cast<arrow::MapType>(type);
    assert(map_type);
    auto key_type = map_type->key_type();
    auto value_type = map_type->item_type();
    auto key_array = value->KeyArray();
    auto value_array = value->ValueArray();
    assert(key_array && value_array);
    assert(key_array->Size() == value_array->Size());
    BinaryArray binary_key_array;
    BinaryArrayWriter binary_key_writer(&binary_key_array, key_array->Size(),
                                        BinaryArrayWriter::GetElementSize(key_type->id()), pool);
    BinaryArray binary_value_array;
    BinaryArrayWriter binary_value_writer(&binary_value_array, value_array->Size(),
                                          BinaryArrayWriter::GetElementSize(value_type->id()),
                                          pool);
    for (int32_t i = 0; i < key_array->Size(); i++) {
        PAIMON_RETURN_NOT_OK(
            WriteBinaryData(key_type, key_array.get(), i, &binary_key_writer, pool));
        PAIMON_RETURN_NOT_OK(
            WriteBinaryData(value_type, value_array.get(), i, &binary_value_writer, pool));
    }
    binary_key_writer.Complete();
    binary_value_writer.Complete();
    return BinaryMap::ValueOf(binary_key_array, binary_value_array, pool);
}

Result<std::shared_ptr<BinaryRow>> BinarySerializerUtils::WriteBinaryRow(
    const std::shared_ptr<InternalRow>& value, const std::shared_ptr<arrow::DataType>& type,
    MemoryPool* pool) {
    if (auto binary_row = std::dynamic_pointer_cast<BinaryRow>(value)) {
        return binary_row;
    }

    auto struct_type = std::dynamic_pointer_cast<arrow::StructType>(type);
    assert(struct_type);
    auto field_count = struct_type->num_fields();
    auto binary_row = std::make_shared<BinaryRow>(field_count);
    BinaryRowWriter binary_writer(binary_row.get(), /*initial_size=*/1024, pool);
    for (int32_t i = 0; i < field_count; i++) {
        PAIMON_RETURN_NOT_OK(
            WriteBinaryData(struct_type->field(i)->type(), value.get(), i, &binary_writer, pool));
    }
    binary_writer.Complete();
    return binary_row;
}

Status BinarySerializerUtils::WriteBinaryData(const std::shared_ptr<arrow::DataType>& type,
                                              const DataGetters* getter, int32_t pos,
                                              BinaryWriter* writer, MemoryPool* pool) {
    assert(getter && writer && pool);
    arrow::Type::type type_id = type->id();
    auto array_writer = dynamic_cast<BinaryArrayWriter*>(writer);
    if (getter->IsNullAt(pos)) {
        // compatible with Java Paimon
        if (array_writer) {
            array_writer->SetNullAt(pos, type_id);
            return Status::OK();
        } else if (type_id != arrow::Type::type::DECIMAL &&
                   type_id != arrow::Type::type::TIMESTAMP) {
            // if row writer, exclude decimal and timestamp when set null
            writer->SetNullAt(pos);
            return Status::OK();
        }
    }
    switch (type_id) {
        case arrow::Type::type::BOOL: {
            writer->WriteBoolean(pos, getter->GetBoolean(pos));
            break;
        }
        case arrow::Type::type::INT8: {
            writer->WriteByte(pos, getter->GetByte(pos));
            break;
        }
        case arrow::Type::type::INT16: {
            writer->WriteShort(pos, getter->GetShort(pos));
            break;
        }
        case arrow::Type::type::DATE32: {
            writer->WriteInt(pos, getter->GetDate(pos));
            break;
        }
        case arrow::Type::type::INT32: {
            writer->WriteInt(pos, getter->GetInt(pos));
            break;
        }
        case arrow::Type::type::INT64: {
            writer->WriteLong(pos, getter->GetLong(pos));
            break;
        }
        case arrow::Type::type::FLOAT: {
            writer->WriteFloat(pos, getter->GetFloat(pos));
            break;
        }
        case arrow::Type::type::DOUBLE: {
            writer->WriteDouble(pos, getter->GetDouble(pos));
            break;
        }
        case arrow::Type::type::STRING: {
            writer->WriteStringView(pos, getter->GetStringView(pos));
            break;
        }
        case arrow::Type::type::BINARY: {
            writer->WriteStringView(pos, getter->GetStringView(pos));
            break;
        }
        case arrow::Type::type::TIMESTAMP: {
            auto timestamp_type = arrow::internal::checked_pointer_cast<arrow::TimestampType>(type);
            assert(timestamp_type);
            int32_t precision = DateTimeUtils::GetPrecisionFromType(timestamp_type);
            if (getter->IsNullAt(pos)) {
                // compatible with Java Paimon
                if (!Timestamp::IsCompact(precision)) {
                    writer->WriteTimestamp(pos, std::nullopt, precision);
                } else {
                    writer->SetNullAt(pos);
                }
            } else {
                writer->WriteTimestamp(pos, getter->GetTimestamp(pos, precision), precision);
            }
            break;
        }
        case arrow::Type::type::DECIMAL: {
            auto* decimal_type = arrow::internal::checked_cast<arrow::Decimal128Type*>(type.get());
            assert(decimal_type);
            auto precision = decimal_type->precision();
            auto scale = decimal_type->scale();
            if (getter->IsNullAt(pos)) {
                // compatible with Java Paimon
                if (!Decimal::IsCompact(precision)) {
                    writer->WriteDecimal(pos, std::nullopt, precision);
                } else {
                    writer->SetNullAt(pos);
                }
            } else {
                writer->WriteDecimal(pos, getter->GetDecimal(pos, precision, scale), precision);
            }
            break;
        }
        case arrow::Type::type::LIST: {
            auto internal_array = getter->GetArray(pos);
            PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<BinaryArray> binary_array,
                                   WriteBinaryArray(internal_array, type, pool));
            writer->WriteArray(pos, *binary_array);
            break;
        }
        case arrow::Type::type::MAP: {
            auto internal_map = getter->GetMap(pos);
            PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<BinaryMap> binary_map,
                                   WriteBinaryMap(internal_map, type, pool));
            writer->WriteMap(pos, *binary_map);
            break;
        }
        case arrow::Type::type::STRUCT: {
            auto internal_row = getter->GetRow(pos, type->num_fields());
            PAIMON_ASSIGN_OR_RAISE(std::shared_ptr<BinaryRow> binary_row,
                                   WriteBinaryRow(internal_row, type, pool));
            writer->WriteRow(pos, *binary_row);
            break;
        }
        default:
            return Status::Invalid(
                fmt::format("type {} not support in WriteBinaryData in binary serializer utils",
                            type->ToString()));
    }
    return Status::OK();
}
}  // namespace paimon
