# 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.

set(ICEBERG_INCLUDES "$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/src>"
                     "$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/src>")
set(ICEBERG_SOURCES
    arrow_c_data_guard_internal.cc
    catalog/memory/in_memory_catalog.cc
    data/data_writer.cc
    data/equality_delete_writer.cc
    data/position_delete_writer.cc
    data/writer.cc
    delete_file_index.cc
    expression/aggregate.cc
    expression/binder.cc
    expression/evaluator.cc
    expression/expression.cc
    expression/expressions.cc
    expression/inclusive_metrics_evaluator.cc
    expression/literal.cc
    expression/manifest_evaluator.cc
    expression/predicate.cc
    expression/projections.cc
    expression/residual_evaluator.cc
    expression/rewrite_not.cc
    expression/strict_metrics_evaluator.cc
    expression/term.cc
    file_reader.cc
    file_writer.cc
    inheritable_metadata.cc
    json_internal.cc
    location_provider.cc
    manifest/manifest_adapter.cc
    manifest/manifest_entry.cc
    manifest/manifest_group.cc
    manifest/manifest_list.cc
    manifest/manifest_reader.cc
    manifest/manifest_util.cc
    manifest/manifest_writer.cc
    manifest/rolling_manifest_writer.cc
    manifest/v1_metadata.cc
    manifest/v2_metadata.cc
    manifest/v3_metadata.cc
    metadata_columns.cc
    metrics_config.cc
    name_mapping.cc
    partition_field.cc
    partition_spec.cc
    partition_summary.cc
    row/arrow_array_wrapper.cc
    row/manifest_wrapper.cc
    row/partition_values.cc
    row/struct_like.cc
    schema.cc
    schema_field.cc
    schema_internal.cc
    schema_util.cc
    snapshot.cc
    sort_field.cc
    sort_order.cc
    statistics_file.cc
    table.cc
    table_identifier.cc
    table_metadata.cc
    table_properties.cc
    table_requirement.cc
    table_requirements.cc
    table_scan.cc
    table_update.cc
    transaction.cc
    transform.cc
    transform_function.cc
    type.cc
    update/expire_snapshots.cc
    update/fast_append.cc
    update/pending_update.cc
    update/set_snapshot.cc
    update/snapshot_update.cc
    update/update_location.cc
    update/update_partition_spec.cc
    update/update_properties.cc
    update/update_schema.cc
    update/update_snapshot_reference.cc
    update/update_sort_order.cc
    update/update_statistics.cc
    util/bucket_util.cc
    util/content_file_util.cc
    util/conversions.cc
    util/decimal.cc
    util/gzip_internal.cc
    util/murmurhash3_internal.cc
    util/property_util.cc
    util/snapshot_util.cc
    util/temporal_util.cc
    util/timepoint.cc
    util/transform_util.cc
    util/truncate_util.cc
    util/type_util.cc
    util/url_encoder.cc
    util/uuid.cc)

set(ICEBERG_STATIC_BUILD_INTERFACE_LIBS)
set(ICEBERG_SHARED_BUILD_INTERFACE_LIBS)
set(ICEBERG_STATIC_INSTALL_INTERFACE_LIBS)
set(ICEBERG_SHARED_INSTALL_INTERFACE_LIBS)

list(APPEND
     ICEBERG_STATIC_BUILD_INTERFACE_LIBS
     nanoarrow::nanoarrow_static
     nlohmann_json::nlohmann_json
     roaring::roaring
     ZLIB::ZLIB)
list(APPEND
     ICEBERG_SHARED_BUILD_INTERFACE_LIBS
     nanoarrow::nanoarrow_shared
     nlohmann_json::nlohmann_json
     roaring::roaring
     ZLIB::ZLIB)
list(APPEND
     ICEBERG_STATIC_INSTALL_INTERFACE_LIBS
     "$<IF:$<BOOL:${NANOARROW_VENDORED}>,iceberg::nanoarrow_static,$<IF:$<TARGET_EXISTS:nanoarrow::nanoarrow_static>,nanoarrow::nanoarrow_static,nanoarrow::nanoarrow_shared>>"
     "$<IF:$<BOOL:${NLOHMANN_JSON_VENDORED}>,iceberg::nlohmann_json,$<IF:$<TARGET_EXISTS:nlohmann_json::nlohmann_json>,nlohmann_json::nlohmann_json,nlohmann_json::nlohmann_json>>"
     "$<IF:$<BOOL:${CROARING_VENDORED}>,iceberg::roaring,roaring::roaring>")
list(APPEND
     ICEBERG_SHARED_INSTALL_INTERFACE_LIBS
     "$<IF:$<BOOL:${NANOARROW_VENDORED}>,iceberg::nanoarrow_shared,$<IF:$<TARGET_EXISTS:nanoarrow::nanoarrow_shared>,nanoarrow::nanoarrow_shared,nanoarrow::nanoarrow_static>>"
     "$<IF:$<BOOL:${NLOHMANN_JSON_VENDORED}>,iceberg::nlohmann_json,$<IF:$<TARGET_EXISTS:nlohmann_json::nlohmann_json>,nlohmann_json::nlohmann_json,nlohmann_json::nlohmann_json>>"
     "$<IF:$<BOOL:${CROARING_VENDORED}>,iceberg::roaring,roaring::roaring>")

add_iceberg_lib(iceberg
                SOURCES
                ${ICEBERG_SOURCES}
                EXTRA_INCLUDES
                ${ICEBERG_INCLUDES}
                SHARED_LINK_LIBS
                ${ICEBERG_SHARED_BUILD_INTERFACE_LIBS}
                STATIC_LINK_LIBS
                ${ICEBERG_STATIC_BUILD_INTERFACE_LIBS}
                STATIC_INSTALL_INTERFACE_LIBS
                ${ICEBERG_STATIC_INSTALL_INTERFACE_LIBS}
                SHARED_INSTALL_INTERFACE_LIBS
                ${ICEBERG_SHARED_INSTALL_INTERFACE_LIBS}
                OUTPUTS
                ICEBERG_LIBRARIES)

iceberg_install_all_headers(iceberg)

add_subdirectory(catalog)
add_subdirectory(data)
add_subdirectory(expression)
add_subdirectory(manifest)
add_subdirectory(row)
add_subdirectory(update)
add_subdirectory(util)

if(ICEBERG_BUILD_BUNDLE)
  set(ICEBERG_BUNDLE_SOURCES
      arrow/arrow_fs_file_io.cc
      arrow/metadata_column_util.cc
      avro/avro_data_util.cc
      avro/avro_direct_decoder.cc
      avro/avro_direct_encoder.cc
      avro/avro_reader.cc
      avro/avro_writer.cc
      avro/avro_register.cc
      avro/avro_schema_util.cc
      avro/avro_stream_internal.cc
      parquet/parquet_data_util.cc
      parquet/parquet_reader.cc
      parquet/parquet_register.cc
      parquet/parquet_schema_util.cc
      parquet/parquet_writer.cc)

  # Libraries to link with exported libiceberg_bundle.{so,a}.
  set(ICEBERG_BUNDLE_STATIC_BUILD_INTERFACE_LIBS)
  set(ICEBERG_BUNDLE_SHARED_BUILD_INTERFACE_LIBS)
  set(ICEBERG_BUNDLE_STATIC_INSTALL_INTERFACE_LIBS)
  set(ICEBERG_BUNDLE_SHARED_INSTALL_INTERFACE_LIBS)

  list(APPEND
       ICEBERG_BUNDLE_STATIC_BUILD_INTERFACE_LIBS
       "$<IF:$<TARGET_EXISTS:iceberg_static>,iceberg_static,iceberg_shared>"
       "$<IF:$<TARGET_EXISTS:Arrow::arrow_static>,Arrow::arrow_static,Arrow::arrow_shared>"
       "$<IF:$<TARGET_EXISTS:Parquet::parquet_static>,Parquet::parquet_static,Parquet::parquet_shared>"
       "$<IF:$<TARGET_EXISTS:avro-cpp::avrocpp_static>,avro-cpp::avrocpp_static,avro-cpp::avrocpp_shared>"
  )
  list(APPEND
       ICEBERG_BUNDLE_SHARED_BUILD_INTERFACE_LIBS
       "$<IF:$<TARGET_EXISTS:iceberg_shared>,iceberg_shared,iceberg_static>"
       "$<IF:$<TARGET_EXISTS:Arrow::arrow_shared>,Arrow::arrow_shared,Arrow::arrow_static>"
       "$<IF:$<TARGET_EXISTS:Parquet::parquet_shared>,Parquet::parquet_shared,Parquet::parquet_static>"
       "$<IF:$<TARGET_EXISTS:avro-cpp::avrocpp_shared>,avro-cpp::avrocpp_shared,avro-cpp::avrocpp_static>"
  )

  list(APPEND
       ICEBERG_BUNDLE_STATIC_INSTALL_INTERFACE_LIBS
       "$<IF:$<TARGET_EXISTS:iceberg::iceberg_static>,iceberg::iceberg_static,iceberg::iceberg_shared>"
       "$<IF:$<BOOL:${ARROW_VENDORED}>,iceberg::arrow_static,$<IF:$<TARGET_EXISTS:Arrow::arrow_static>,Arrow::arrow_static,Arrow::arrow_shared>>"
       "$<IF:$<BOOL:${ARROW_VENDORED}>,iceberg::parquet_static,$<IF:$<TARGET_EXISTS:Parquet::parquet_static>,Parquet::parquet_static,Parquet::parquet_shared>>"
       "$<IF:$<BOOL:${AVRO_VENDORED}>,iceberg::avrocpp_s,$<IF:$<TARGET_EXISTS:avro-cpp::avrocpp_static>,avro-cpp::avrocpp_static,avro-cpp::avrocpp_shared>>"
  )
  list(APPEND
       ICEBERG_BUNDLE_SHARED_INSTALL_INTERFACE_LIBS
       "$<IF:$<TARGET_EXISTS:iceberg::iceberg_shared>,iceberg::iceberg_shared,iceberg::iceberg_static>"
       "$<IF:$<BOOL:${ARROW_VENDORED}>,iceberg::arrow_static,$<IF:$<TARGET_EXISTS:Arrow::arrow_shared>,Arrow::arrow_shared,Arrow::arrow_static>>"
       "$<IF:$<BOOL:${ARROW_VENDORED}>,iceberg::parquet_static,$<IF:$<TARGET_EXISTS:Parquet::parquet_shared>,Parquet::parquet_shared,Parquet::parquet_static>>"
       "$<IF:$<BOOL:${AVRO_VENDORED}>,iceberg::avrocpp_s,$<IF:$<TARGET_EXISTS:avro-cpp::avrocpp_shared>,avro-cpp::avrocpp_shared,avro-cpp::avrocpp_static>>"
  )

  add_iceberg_lib(iceberg_bundle
                  SOURCES
                  ${ICEBERG_BUNDLE_SOURCES}
                  SHARED_LINK_LIBS
                  ${ICEBERG_BUNDLE_SHARED_BUILD_INTERFACE_LIBS}
                  STATIC_LINK_LIBS
                  ${ICEBERG_BUNDLE_STATIC_BUILD_INTERFACE_LIBS}
                  STATIC_INSTALL_INTERFACE_LIBS
                  ${ICEBERG_BUNDLE_STATIC_INSTALL_INTERFACE_LIBS}
                  SHARED_INSTALL_INTERFACE_LIBS
                  ${ICEBERG_BUNDLE_SHARED_INSTALL_INTERFACE_LIBS}
                  OUTPUTS
                  ICEBERG_BUNDLE_LIBRARIES)

  add_subdirectory(arrow)
  add_subdirectory(avro)
  add_subdirectory(parquet)
endif()

iceberg_install_cmake_package(iceberg iceberg_targets)

if(ICEBERG_BUILD_TESTS)
  add_subdirectory(test)
endif()
