# Copyright (c) 2021 Huawei Device Co., Ltd.
# Licensed 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.

import("//build/templates/common/copy.gni")

template("ohos_prebuilt_executable") {
  assert(defined(invoker.source), "source must be defined for ${target_name}.")

  source = invoker.source
  support_arm64e = (defined(invoker.support_arm64e) && invoker.support_arm64e)

  if (defined(invoker.output)) {
    _copy_output = "${target_out_dir}/${invoker.output}"
  } else {
    if (support_arm64e && current_toolchain == "${arm64e_toolchain}") {
      source_parts = string_split(invoker.source, "/")
      length = 0
      foreach(i, source_parts) {
        length += 1
      }
      file_name = source_parts[length - 1]
      source = string_replace(invoker.source, file_name, "arm64e/$file_name")
      _copy_output = "${target_out_dir}/${source}"

      if (defined(invoker.install_images)) {
        invoker.install_images = []
        invoker.install_images = [ "system_arm64e" ]
      }
    } else {
      _copy_output = "${target_out_dir}/${invoker.source}"
    }
  }

  if (!defined(invoker.deps)) {
    invoker.deps = []
  }

  if (!defined(invoker.stable)) {
    invoker.stable = false
  }

  deps_info = []
  foreach(dep, invoker.deps) {
    info = {
    }
    info = {
      target_out_dir =
          rebase_path(get_label_info(dep, "target_out_dir"), root_build_dir)
      target_name = get_label_info(dep, "name")
    }
    deps_info += [ info ]
  }
  module_label = get_label_info(":${target_name}", "label_with_toolchain")
  target_deps_data = {
    label = module_label
    module_deps_info = deps_info
    type = "executable"
    prebuilt = true
    stable = invoker.stable
    toolchain = get_label_info(":${target_name}", "toolchain")
    source_path = rebase_path(invoker.source, root_build_dir)
    output_path = rebase_path(_copy_output, root_build_dir)
  }
  write_file("${target_out_dir}/${target_name}_deps_data.json",
             target_deps_data,
             "json")

  ohos_copy(target_name) {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",

                             "deps",
                             "external_deps",
                             "public_external_deps",
                             "public_configs",
                             "subsystem_name",
                             "part_name",

                             # For generate_module_info
                             "install_images",
                             "module_install_dir",
                             "relative_install_dir",
                             "symlink_target_name",

                             # Open source license related
                             "license_file",
                             "license_as_sources",
                           ])
    sources = [ source ]
    outputs = [ _copy_output ]
    module_type = "bin"
    prebuilt = true
    install_enable = false
    enable_strip = false
    if (defined(invoker.enable_strip) && invoker.enable_strip) {
      enable_strip = true
    }
    if (defined(invoker.install_enable)) {
      install_enable = invoker.install_enable
    }

    if (support_arm64e && current_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") {
      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":${target_name}($arm64e_toolchain)" ]
    }
  }
}

template("ohos_prebuilt_shared_library") {
  assert(defined(invoker.source), "source must be defined for ${target_name}.")

  source = invoker.source
  support_arm64e = (defined(invoker.support_arm64e) && invoker.support_arm64e)
  if (current_toolchain == "${arm64e_toolchain}" && support_arm64e) {
    source_parts = string_split(invoker.source, "/")
    length = 0
    foreach(i, source_parts) {
      length += 1
    }
    file_name = source_parts[length - 1]
    source = string_replace(invoker.source, file_name, "arm64e/$file_name")

    if (defined(invoker.install_images)) {
      invoker.install_images = []
      invoker.install_images = [ "system_arm64e" ]
    }
  }

  if (defined(invoker.output)) {
    _copy_output = "${target_out_dir}/${invoker.output}"
  } else {
    _copy_output = "${target_out_dir}/${source}"
  }
  config("${target_name}__config") {
    libs = [ _copy_output ]
  }

  if (!defined(invoker.deps)) {
    invoker.deps = []
  }

  if (!defined(invoker.stable)) {
    invoker.stable = false
  }

  # auto set auto_relative_install_dir by innerapi_tags
  if (defined(invoker.innerapi_tags)) {
    is_chipsetsdk = false
    is_platformsdk = false
    is_platformsdk_indirect = false
    is_passthrough = false
    is_passthrough_indirect = false
    is_llndk = false
    is_chipsetsdk_indirect = false
    is_chipsetsdk_sp = false
    is_chipsetsdk_sp_indirect = false

    foreach(tag, filter_include(invoker.innerapi_tags, [ "llndk" ])) {
      is_llndk = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "chipsetsdk" ])) {
      is_chipsetsdk = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "chipsetsdk_indirect" ])) {
      is_chipsetsdk_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "chipsetsdk_sp" ])) {
      is_chipsetsdk_sp = true
    }
    foreach(
        tag,
        filter_include(invoker.innerapi_tags, [ "chipsetsdk_sp_indirect" ])) {
      is_chipsetsdk_sp_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "platformsdk" ])) {
      is_platformsdk = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "platformsdk_indirect" ])) {
      is_platformsdk_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "passthrough" ])) {
      is_passthrough = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "passthrough_indirect" ])) {
      is_passthrough_indirect = true
    }

    if (is_chipsetsdk && (is_chipsetsdk_indirect || is_chipsetsdk_sp || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk tags cannot coexist with [chipsetsdk_indirect,chipsetsdk_sp,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_indirect && (is_chipsetsdk || is_chipsetsdk_sp || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk_indirect tags cannot coexist with [chipsetsdk,chipsetsdk_sp,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_sp && (is_chipsetsdk || is_chipsetsdk_indirect || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk_sp tags cannot coexist with [chipsetsdk,chipsetsdk_indirect,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_sp_indirect && (is_chipsetsdk || is_chipsetsdk_sp || is_chipsetsdk_indirect)) {
      assert(false, "chipsetsdk_sp_indirect tags cannot coexist with [chipsetsdk,chipsetsdk_indirect,chipsetsdk_sp]")
    }

    if (is_platformsdk) {
      auto_relative_install_dir = platformsdk_dir
    }

    if (is_platformsdk_indirect) {
      auto_relative_install_dir = platformsdk_dir
    }

    if (is_chipsetsdk) {
      auto_relative_install_dir = chipset_sdk_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_indirect) {
      auto_relative_install_dir = chipset_sdk_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_sp) {
      auto_relative_install_dir = chipset_sdk_sp_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_sp_indirect) {
      auto_relative_install_dir = chipset_sdk_sp_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_passthrough) {
      auto_relative_install_dir = passthrough_dir
    }
    if (is_passthrough_indirect) {
      auto_relative_install_dir = passthrough_indirect_dir
    }

    if (is_llndk) {
      auto_relative_install_dir = llndk_dir
    }
    is_ndk = false
    foreach(tag, filter_include(invoker.innerapi_tags, [ "ndk" ])) {
      is_ndk = true
    }
    if (is_ndk) {
      auto_relative_install_dir = ndk_dir
    }
  }

  deps_info = []
  foreach(dep, invoker.deps) {
    info = {
    }
    info = {
      target_out_dir =
          rebase_path(get_label_info(dep, "target_out_dir"), root_build_dir)
      target_name = get_label_info(dep, "name")
    }
    deps_info += [ info ]
  }
  module_label = get_label_info(":${target_name}", "label_with_toolchain")
  target_deps_data = {
    label = module_label
    module_deps_info = deps_info
    type = "shared_library"
    prebuilt = true
    stable = invoker.stable
    toolchain = get_label_info(":${target_name}", "toolchain")
    source_path = rebase_path(source, root_build_dir)
    output_path = rebase_path(_copy_output, root_build_dir)
  }
  write_file("${target_out_dir}/${target_name}_deps_data.json",
             target_deps_data,
             "json")

  ohos_copy(target_name) {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",

                             "deps",
                             "external_deps",
                             "public_external_deps",
                             "public_configs",
                             "subsystem_name",
                             "part_name",

                             # For generate_module_info
                             "install_images",
                             "module_install_dir",
                             "symlink_target_name",
                             "innerapi_tags",
                             "symlink_ext",

                             # Open source license related
                             "license_file",
                             "license_as_sources",
                           ])
    sources = [ source ]
    outputs = [ _copy_output ]
    module_type = "lib"
    prebuilt = true
    install_enable = true
    enable_strip = false
    if (defined(invoker.enable_strip) && invoker.enable_strip) {
      enable_strip = true
    }

    if (!defined(invoker.copy_linkable_file) && !enable_strip) {
      copy_linkable_file = true
    }
    mini_debug = false
    if (defined(invoker.mini_debug) && invoker.mini_debug) {
      mini_debug = true
    }
    if (defined(invoker.install_enable)) {
      install_enable = invoker.install_enable
    }

    # update relative_install_dir if auto_relative_install_dir defined
    if (defined(auto_relative_install_dir) && auto_relative_install_dir != "") {
      relative_install_dir = auto_relative_install_dir
    }
    if (defined(invoker.relative_install_dir)) {
      relative_install_dir = invoker.relative_install_dir
    }

    if (defined(invoker.innerapi_tags)) {
      if (defined(softlink_path) && softlink_path != "") {
        softlink_create_path = softlink_path
      }
    }
    if (!defined(public_configs)) {
      public_configs = []
    }
    public_configs += [ ":${target_name}__config" ]
    if (support_arm64e && current_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") {
      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":${target_name}($arm64e_toolchain)" ]
    }
  }
}

template("ohos_prebuilt_static_library") {
  assert(defined(invoker.source), "source must be defined for ${target_name}.")
  source = invoker.source
  support_arm64e = (defined(invoker.support_arm64e) && invoker.support_arm64e)

  if (defined(invoker.output)) {
    _copy_output = "${target_out_dir}/${invoker.output}"
  } else {
    if (support_arm64e && current_toolchain == "${arm64e_toolchain}") {
      source_parts = string_split(invoker.source, "/")
      length = 0
      foreach(i, source_parts) {
        length += 1
      }
      file_name = source_parts[length - 1]
      source = string_replace(invoker.source, file_name, "arm64e/$file_name")
      _copy_output = "${target_out_dir}/${source}"
    } else {
      _copy_output = "${target_out_dir}/${invoker.source}"
    }
  }
  config("${target_name}__config") {
    libs = [ _copy_output ]
  }
  ohos_copy(target_name) {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",
                             "deps",
                             "public_deps",
                             "external_deps",
                             "public_external_deps",
                             "public_configs",
                             "subsystem_name",
                             "part_name",
                             "copy_linkable_file",

                             # Open source license related
                             "license_file",
                             "license_as_sources",
                           ])
    sources = [ source ]
    outputs = [ _copy_output ]
    bypass_module_info_generation = true
    if (!defined(public_configs)) {
      public_configs = []
    }
    public_configs += [ ":${target_name}__config" ]
    if (support_arm64e && current_toolchain == "//build/toolchain/ohos:ohos_clang_arm64") {
      if (!defined(deps)) {
        deps = []
      }
      deps += [ ":${target_name}($arm64e_toolchain)" ]
    }
  }
}

template("ohos_prebuilt_etc") {
  assert(defined(invoker.source), "source must be defined for ${target_name}.")

  if (defined(invoker.output)) {
    _copy_output = "${target_out_dir}/${invoker.output}"
  } else {
    _copy_output = "${target_out_dir}/${invoker.source}"
  }

  source_path = rebase_path(invoker.source, root_build_dir)
  module_label = get_label_info(":${target_name}", "label_with_toolchain")
  target_deps_data = {
    label = module_label
    type = "etc"
    prebuilt = true
    source_path = source_path
    output_path = rebase_path(_copy_output, root_build_dir)
  }
  write_file("${target_out_dir}/${target_name}_deps_data.json",
             target_deps_data,
             "json")

  ohos_copy(target_name) {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",

                             "deps",
                             "external_deps",
                             "public_external_deps",
                             "public_configs",
                             "subsystem_name",
                             "part_name",

                             # For generate_module_info
                             "install_images",
                             "module_install_dir",
                             "relative_install_dir",
                             "symlink_target_name",
                             "copy_linkable_file",

                             # Open source license related
                             "license_file",
                             "license_as_sources",
                           ])
    sources = [ invoker.source ]
    outputs = [ _copy_output ]
    module_type = "etc"
    prebuilt = true
    install_enable = true
    if (defined(invoker.install_enable)) {
      install_enable = invoker.install_enable
    }
    if (defined(invoker.symlink_path)) {
      symlink_path = invoker.symlink_path
    }
  }
}

template("ohos_prebuilt_rust_library") {
  assert(defined(invoker.source), "source must be defined for ${target_name}.")

  if (defined(invoker.output)) {
    _copy_output = "${target_out_dir}/${invoker.output}"
  } else {
    _copy_output = "${target_out_dir}/${invoker.source}"
  }
  config("${target_name}__config") {
    libs = [ _copy_output ]
  }

  if (!defined(invoker.deps)) {
    invoker.deps = []
  }

  if (!defined(invoker.stable)) {
    invoker.stable = false
  }

  # auto set auto_relative_install_dir by innerapi_tags
  if (defined(invoker.innerapi_tags)) {
    is_chipsetsdk = false
    is_platformsdk = false
    is_platformsdk_indirect = false
    is_passthrough = false
    is_passthrough_indirect = false
    is_llndk = false
    is_chipsetsdk_indirect = false
    is_chipsetsdk_sp = false
    is_chipsetsdk_sp_indirect = false

    foreach(tag, filter_include(invoker.innerapi_tags, [ "llndk" ])) {
      is_llndk = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "chipsetsdk" ])) {
      is_chipsetsdk = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "chipsetsdk_indirect" ])) {
      is_chipsetsdk_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "chipsetsdk_sp" ])) {
      is_chipsetsdk_sp = true
    }
    foreach(
        tag,
        filter_include(invoker.innerapi_tags, [ "chipsetsdk_sp_indirect" ])) {
      is_chipsetsdk_sp_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "platformsdk" ])) {
      is_platformsdk = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "platformsdk_indirect" ])) {
      is_platformsdk_indirect = true
    }
    foreach(tag, filter_include(invoker.innerapi_tags, [ "passthrough" ])) {
      is_passthrough = true
    }
    foreach(tag,
            filter_include(invoker.innerapi_tags, [ "passthrough_indirect" ])) {
      is_passthrough_indirect = true
    }

    if (is_chipsetsdk && (is_chipsetsdk_indirect || is_chipsetsdk_sp || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk tags cannot coexist with [chipsetsdk_indirect,chipsetsdk_sp,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_indirect && (is_chipsetsdk || is_chipsetsdk_sp || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk_indirect tags cannot coexist with [chipsetsdk,chipsetsdk_sp,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_sp && (is_chipsetsdk || is_chipsetsdk_indirect || is_chipsetsdk_sp_indirect)) {
      assert(false, "chipsetsdk_sp tags cannot coexist with [chipsetsdk,chipsetsdk_indirect,chipsetsdk_sp_indirect]")
    } else if (is_chipsetsdk_sp_indirect && (is_chipsetsdk || is_chipsetsdk_sp || is_chipsetsdk_indirect)) {
      assert(false, "chipsetsdk_sp_indirect tags cannot coexist with [chipsetsdk,chipsetsdk_indirect,chipsetsdk_sp]")
    }

    if (is_platformsdk) {
      auto_relative_install_dir = platformsdk_dir
    }

    if (is_platformsdk_indirect) {
      auto_relative_install_dir = platformsdk_dir
    }

    if (is_chipsetsdk) {
      auto_relative_install_dir = chipset_sdk_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_indirect) {
      auto_relative_install_dir = chipset_sdk_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_sp) {
      auto_relative_install_dir = chipset_sdk_sp_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_chipsetsdk_sp_indirect) {
      auto_relative_install_dir = chipset_sdk_sp_dir
      if (is_platformsdk || is_platformsdk_indirect) {
        softlink_path = platformsdk_dir
      }
    }

    if (is_passthrough) {
      auto_relative_install_dir = passthrough_dir
    }
    if (is_passthrough_indirect) {
      auto_relative_install_dir = passthrough_indirect_dir
    }

    if (is_llndk) {
      auto_relative_install_dir = llndk_dir
    }
    is_ndk = false
    foreach(tag, filter_include(invoker.innerapi_tags, [ "ndk" ])) {
      is_ndk = true
    }
    if (is_ndk) {
      auto_relative_install_dir = ndk_dir
    }
  }

  deps_info = []
  foreach(dep, invoker.deps) {
    info = {
    }
    info = {
      target_out_dir =
          rebase_path(get_label_info(dep, "target_out_dir"), root_build_dir)
      target_name = get_label_info(dep, "name")
    }
    deps_info += [ info ]
  }
  module_label = get_label_info(":${target_name}", "label_with_toolchain")
  target_deps_data = {
    label = module_label
    module_deps_info = deps_info
    type = "rust_library"
    prebuilt = true
    stable = invoker.stable
    toolchain = get_label_info(":${target_name}", "toolchain")
    source_path = rebase_path(invoker.source, root_build_dir)
    output_path = rebase_path(_copy_output, root_build_dir)
  }
  write_file("${target_out_dir}/${target_name}_deps_data.json",
             target_deps_data,
             "json")

  ohos_copy(target_name) {
    forward_variables_from(invoker,
                           [
                             "testonly",
                             "visibility",
                             "rust_crate_name",
                             "rust_crate_type",
                             "copy_linkable_file",
                             "deps",
                             "external_deps",
                             "public_external_deps",
                             "public_configs",
                             "subsystem_name",
                             "part_name",

                             # For generate_module_info
                             "install_images",
                             "module_install_dir",
                             "symlink_target_name",
                             "innerapi_tags",
                             "symlink_ext",

                             # Open source license related
                             "license_file",
                             "license_as_sources",
                           ])
    sources = [ invoker.source ]
    outputs = [ _copy_output ]
    module_type = "lib"
    prebuilt = true
    install_enable = true
    if (!defined(invoker.copy_linkable_file)) {
      copy_linkable_file = true
    }
    if (defined(invoker.install_enable)) {
      install_enable = invoker.install_enable
    }

    # update relative_install_dir if auto_relative_install_dir defined
    if (defined(auto_relative_install_dir) && auto_relative_install_dir != "") {
      relative_install_dir = auto_relative_install_dir
    }
    if (defined(invoker.relative_install_dir)) {
      relative_install_dir = invoker.relative_install_dir
    }
    if (defined(invoker.innerapi_tags)) {
      if (defined(softlink_path) && softlink_path != "") {
        softlink_create_path = softlink_path
      }
    }
    if (!defined(public_configs)) {
      public_configs = []
    }
    public_configs += [ ":${target_name}__config" ]
  }
}