# Copyright 2023 The Lynx Authors. All rights reserved.
# Licensed under the Apache License Version 2.0 that can be found in the
# LICENSE file in the root directory of this source tree.

import("../../config.gni")
import("../../oliver/oliver.gni")
import("../../testing/test.gni")
import("../include/base_public_headers.gni")
import("base.gni")

static_library("base_static") {
  sources = [
    "../platform/windows/lynx_base_env.cc",
    "../platform/windows/lynx_base_env.h",
  ]
  if (is_mac) {
    # Native desktop consumers and tests do not link the Objective-C logger.
    # Keep the fallback in the archive so platform-provided symbols take
    # precedence when the platform logger is linked.
    sources += [
      "log/logging_base.cc",
      "log/logging_platform_default.cc",
    ]
  }
  deps = [ ":base_group" ]
  configs += [ ":base_private_config" ]
}

group("base_group") {
  public_deps = [
    ":base_core",
    ":base_log",
    ":base_trace",
    ":datauri_utils",
    ":string_utils",
    ":time_utils",
    ":values",
  ]
}

group("base_for_oliver") {
  public_deps = [
    ":base_log",
    ":base_values",
    ":string_utils",
    ":time_utils",
  ]
  if (is_oliver_ssr || is_oliver_node_lynx) {
    public_deps += [
      ":base_core",
      ":base_trace",
    ]
  }
}

config("base_public_config") {
  defines = []
  cflags = []
  if (!base_export_symbols) {
    defines += [ "BASE_NO_EXPORT" ]
  }
  if (!is_debug) {
    defines += [ "NDEBUG" ]
  }

  if (is_android) {
    defines += [
      "GNU_SUPPORT=1",
      "OS_ANDROID=1",
      "OS_POSIX=1",
    ]
  } else if (is_ios) {
    defines += [
      "OS_IOS=1",
      "OS_POSIX=1",
    ]
  } else if (is_mac) {
    defines += [
      "OS_OSX=1",
      "OS_POSIX=1",
    ]
  } else if (is_win) {
    defines += [
      "OS_WIN=1",
      "_CRT_SECURE_NO_WARNINGS=1",
      "lynx_EXPORTS",
    ]
  }
  configs = [ ":base_log_public_config" ]
}

config("base_private_config") {
  cflags = [
    "-ffunction-sections",
    "-fdata-sections",
    "-fno-exceptions",
    "-fvisibility=hidden",
    "-fvisibility-inlines-hidden",
    "-fno-short-enums",
    "-fno-stack-protector",
    "-fno-strict-aliasing",
    "-Wextra",
    "-Wno-unused-parameter",
  ]
  cflags_c = []
  cflags_cc = [
    "-fno-rtti",
    "-std=c++17",
    "-Wl,-ldl",
    "-Wno-unused-command-line-argument",
  ]
  configs = []
  if (is_debug) {
    cflags_cc += [ "-g" ]
  }

  defines = []
}

config("base_log_public_config") {
  defines = []
  if (enable_lite && enable_lite_production) {
    defines += [ "LYNX_MIN_LOG_LEVEL=5" ]
  } else if (is_oliver_ssr) {
    defines += [ "LYNX_MIN_LOG_LEVEL=5" ]
  } else if (is_debug) {
    # In debug mode, logs of all levels will be output.
    defines += [ "LYNX_MIN_LOG_LEVEL=0" ]
  } else {
    # In release mode, logs with a priority higher than LOG_DEBUG will be output.
    defines += [ "LYNX_MIN_LOG_LEVEL=2" ]
  }
  if (is_mac) {
    configs = darwin_config
  }
}

# Share declarations without pulling base implementation objects into consumers.
lynx_base_source_set("base_public_headers") {
  sources = base_public_headers
}

lynx_base_source_set("base_log_headers") {
  public_configs = [ ":base_log_public_config" ]
  sources = base_log_public_headers
}

lynx_base_source_set("base_log") {
  public_configs = [ ":base_log_public_config" ]
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = base_log_public_headers
  public_deps = [ ":base_log_headers" ]

  sources = [
    "debug/lynx_error.cc",
    "log/alog_wrapper.cc",
    "log/log_stream.cc",
    "log/logging.cc",
  ]
  if (is_android) {
    sources += [ "log/logging_android.cc" ]
  } else if (is_apple) {
    sources += [ "log/logging_darwin.mm" ]
  } else if (is_harmony) {
    sources += [
      "log/logging_harmony.cc",
      "log/logging_harmony.h",
    ]
  } else if (is_win || is_linux) {
    sources += [
      "log/logging_base.cc",
      "log/logging_platform_default.cc",
    ]
  }
  if (!is_win) {
    # Windows do not overwrite this file
    sources += [ "debug/backtrace.cc" ]
  }

  deps = [ "../../third_party/rapidjson:rapidjson" ]
}

lynx_base_source_set("time_utils") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = time_utils_public_headers
  sources = time_utils_public_headers + [ "timer/time_utils.cc" ]
}

lynx_base_source_set("base_trace") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = base_trace_public_headers
  sources = base_trace_public_headers + [
              "base_trace/base_trace_event_def.h",
              "base_trace/trace_event.h",
              "base_trace/trace_event_utils.cc",
            ]
  if (is_android) {
    sources += [ "base_trace/trace_android.cc" ]
  } else if (is_harmony) {
    sources += [ "base_trace/trace_harmony.cc" ]
  }
}

lynx_base_source_set("base_core") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = base_core_public_headers
  public_deps = [
    ":string_utils",
    ":time_utils",
    ":values",
  ]

  sources = base_core_public_headers + [
              "./fml/raster_thread_merger.cc",
              "./fml/shared_thread_merger.cc",
              "application_directory/application_directory.cc",
              "application_directory/application_directory_impl.h",
              "buffer.cc",
              "file_utils.cc",
              "fml/concurrent_message_loop.cc",
              "fml/cpu_affinity.cc",
              "fml/memory/task_runner_checker.cc",
              "fml/message_loop.cc",
              "fml/message_loop_impl.cc",
              "fml/message_loop_task_queues.cc",
              "fml/platform/thread_config_setter.cc",
              "fml/synchronization/count_down_latch.cc",
              "fml/synchronization/semaphore.cc",
              "fml/synchronization/sync_switch.cc",
              "fml/synchronization/waitable_event.cc",
              "fml/task_runner.cc",
              "fml/task_source.cc",
              "fml/thread.cc",
              "fml/thread_name_setter.h",
              "fml/time/time_point.cc",
              "fml/time/timer.cc",
              "fml/unique_fd.cc",
              "md5.cc",
              "memory/process_memory_info.cc",
              "notification_center.cc",
              "thread/timed_task.cc",
              "vector.cc",
            ]

  if (is_ios) {
    sources += [ "application_directory/application_directory_ios.mm" ]
  } else if (is_apple) {
    sources += [ "application_directory/application_directory_darwin.mm" ]
  } else if (is_win) {
    sources += [ "application_directory/application_directory_win.cc" ]
  } else if (is_linux) {
    sources += [ "application_directory/application_directory_linux.cc" ]
  } else {
    sources += [ "application_directory/application_directory_default.cc" ]
  }

  if (is_android || is_linux) {
    sources += [ "fml/platform/linux/timerfd.cc" ]
  }

  if (is_android) {
    sources += [
      "application_directory/application_directory_android.cc",
      "fml/platform/android/cpu_affinity.cc",
      "fml/platform/android/thread_config_setter_android.cc",
      "fml/platform/posix/thread_name_setter_posix.cc",
      "fml/synchronization/shared_mutex_std.cc",
      "platform/android/java_type.cc",
      "platform/android/jni_convert_helper.cc",
      "platform/android/jni_utils.cc",
      "platform/android/process_memory_info.cc",
      "platform/android/scoped_java_ref.cc",
    ]
    if (enable_unittests) {
      # Use NDK implementation of message loop instead of JNI as UT doesn't have a JVM.
      # Also ref to https://github.com/flutter/engine/pull/29889/files and
      # https://github.com/flutter/engine/pull/31750 for historical reasons.
      sources += [ "fml/platform/android/message_loop_android_ndk.cc" ]
    } else {
      sources += [ "fml/platform/android/message_loop_android.cc" ]
    }
  } else if (is_harmony) {
    sources += [
      "fml/platform/harmony/message_loop_harmony.cc",
      "fml/platform/linux/timerfd.cc",
      "fml/platform/posix/thread_name_setter_posix.cc",
      "fml/synchronization/shared_mutex_std.cc",
      "platform/harmony/harmony_vsync_manager.cc",
      "platform/harmony/napi_util.cc",
    ]
  } else if (is_linux) {
    sources += [
      "fml/platform/posix/thread_name_setter_posix.cc",
      "fml/synchronization/shared_mutex_std.cc",
    ]
    if (!use_custom_message_loop) {
      sources += [ "fml/platform/linux/message_loop_linux.cc" ]
    }
  } else if (is_apple) {
    sources += [
      "fml/platform/darwin/thread_config_setter_darwin.mm",
      "fml/platform/darwin/thread_name_setter_darwin.cc",
      "fml/synchronization/shared_mutex_posix.cc",
    ]

    if (!use_custom_message_loop) {
      sources += [ "fml/platform/darwin/message_loop_darwin.mm" ]
    }

    flutter_cflags_objc = [
      "-Werror=overriding-method-mismatch",
      "-Werror=undeclared-selector",
    ]
    flutter_cflags_objcc = flutter_cflags_objc

    cflags_objc = flutter_cflags_objc
    cflags_objcc = flutter_cflags_objcc
    frameworks = [ "Foundation.framework" ]
  } else if (is_win) {
    sources += [
      "fml/platform/win/message_loop_win.cc",
      "fml/platform/win/task_runner_win32.cc",
      "fml/platform/win/task_runner_win32_window.cc",
      "fml/platform/win/thread_name_setter_win.cc",
      "fml/synchronization/shared_mutex_std.cc",
      "string/string_conversion_win.cc",
    ]
  }

  deps = [ ":datauri_utils" ]

  libs = []
  if (is_android) {
    libs += [ "android" ]
  }
  if (is_harmony) {
    libs += [ "ohhidebug" ]
  }
  if (is_win) {
    libs += [
      "psapi.lib",
      "shell32.lib",
      "user32.lib",
    ]
  }
}

if (enable_unittests) {
  unittest_exec("base_unittests_exec") {
    testonly = true
    sources = [
      "algorithm_unittest.cc",
      "auto_create_optional_unittest.cc",
      "auto_reset_unittest.cc",
      "boost/unordered_unittest.cc",
      "buffer_unittest.cc",
      "bundled_optional_unittest.cc",
      "closure_unittest.cc",
      "concurrent_queue_unittest.cc",
      "datauri_utils_unittest.cc",
      "debug/lynx_error_unittest.cc",
      "expected_unittest.cc",
      "flex_optional_unittest.cc",
      "fml/cpu_affinity_unittests.cc",
      "fml/hash_combine_unittests.cc",
      "fml/memory/ref_counted_unittest.cc",
      "fml/memory/task_runner_checker_unittest.cc",
      "fml/memory/weak_ptr_unittest.cc",
      "fml/message_loop_impl_unittests.cc",
      "fml/message_loop_task_queues_merge_unmerge_unittests.cc",
      "fml/message_loop_task_queues_unittests.cc",
      "fml/message_loop_unittests.cc",
      "fml/raster_thread_merger_unittests.cc",
      "fml/synchronization/count_down_latch_unittests.cc",
      "fml/synchronization/semaphore_unittest.cc",
      "fml/synchronization/sync_switch_unittest.cc",
      "fml/synchronization/waitable_event_unittest.cc",
      "fml/task_runner_unittests.cc",
      "fml/task_source_unittests.cc",
      "fml/thread_unittests.cc",
      "fml/time/chrono_timestamp_provider.cc",
      "fml/time/time_delta_unittest.cc",
      "fml/time/time_point_unittest.cc",
      "fml/time/time_unittest.cc",
      "geometry_unittest.cc",
      "hybrid_map_unittest.cc",
      "linked_hash_map_unittest.cc",
      "log/log_stream_unittest.cc",
      "log/logging_unittest.cc",
      "lynx_actor_unittest.cc",
      "memory/process_memory_info_unittest.cc",
      "notification_center_unittest.cc",
      "path_utils_unittest.cc",
      "sorted_for_each_unittest.cc",
      "string/string_number_convert_unittest.cc",
      "string/string_utils_unittest.cc",
      "string/unicode_decode_utils_unittest.cc",
      "thread/timed_task_unittest.cc",
      "timer/time_utils_unittest.cc",
      "to_underlying_unittest.cc",
      "type_traits_addon_unittest.cc",
      "value/base_value_unittest.cc",
      "value/lynx_value_extended_empty.cc",
      "value/path_parser_unittest.cc",
      "vector_unittest.cc",
      "version_unittest.cc",
    ]
    if (is_android || is_harmony) {
      sources +=
          [ "application_directory/application_directory_mobile_unittest.cc" ]
    } else if (is_apple || is_win || is_linux) {
      sources += [ "application_directory/application_directory_unittest.cc" ]
    }
    if (is_mac) {
      sources += [ "fml/platform/darwin/cf_utils_unittests.mm" ]
    }
    deps = [
      ":base_core",
      ":base_log",
      ":base_values",
      "//third_party/googletest:gtest",
    ]
  }
}

lynx_base_source_set("string_utils") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = string_utils_public_headers
  sources = string_utils_public_headers + [
              "string/quickjs_dtoa.c",
              "string/string_number_convert.cc",
              "string/string_utils.cc",
              "string/unicode_decode_utils.cc",
            ]
}

# TODO(chenyouhui): Merge 'values' into 'base_values' target
config("value_config") {
  cflags_cc = [
    "-Wno-missing-field-initializers",
    "-Wno-error=missing-field-initializers",
  ]
}
lynx_base_source_set("base_values") {
  public = base_values_public_headers
  sources = base_values_public_headers + [
              "value/base_value.cc",
              "value/base_value_print.cc",
              "value/byte_array.cc",
              "value/lynx_value_api_impl.cc",
              "value/path_parser.cc",
              "value/table.cc",
            ]
  public_deps = [ ":values" ]
  configs = [ ":value_config" ]
}

lynx_base_source_set("base_values_extended") {
  sources = [ "value/lynx_value_extended_empty.cc" ]
}

lynx_base_source_set("values") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = values_public_headers

  sources = values_public_headers + [ "value/base_string.cc" ]
}

lynx_base_source_set("datauri_utils") {
  visibility = [
    ":*",
    "../platform/darwin:*",
  ]
  public = datauri_utils_public_headers
  sources = datauri_utils_public_headers + [ "datauri_utils.cc" ]

  public_deps = [ "//third_party/modp_b64" ]
}