# 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/config/python.gni")
import("//build/ohos_var.gni")
import("//build/templates/metadata/module_info.gni")

if (is_ohos) {
  import("//build/config/ohos/abi.gni")
}

template("merge_profile") {
  forward_variables_from(invoker, [ "testonly" ])
  assert(defined(invoker.hap_profile),
         "hap_profile must be defined for compile_resources")
  action(target_name) {
    forward_variables_from(invoker,
                           [
                             "meta_data",
                             "hap_profile",
                             "generated_profile",
                             "deps",
                           ])
    script = "//build/scripts/merge_profile.py"
    depfile = "$target_gen_dir/$target_name.d"

    _rebased_metadata = rebase_path(meta_data, root_build_dir)
    inputs = [
      meta_data,
      hap_profile,
    ]
    args = [
      "--resources-dir=@FileArg($_rebased_metadata:root:resources)",
      "--depfile",
      rebase_path(depfile, root_build_dir),
      "--app-profile=@FileArg($_rebased_metadata:root:app_profile)",
      "--hap-profile",
      rebase_path(hap_profile, root_build_dir),
      "--generated-profile",
      rebase_path(generated_profile, root_build_dir),
      "--release-type",
      release_type,
      "--api-version",
      api_version,
    ]
    outputs = [ generated_profile ]
  }
}

template("compile_resources") {
  forward_variables_from(invoker, [ "testonly" ])
  assert(defined(invoker.hap_profile),
         "hap_profile must be defined for compile_resources")
  assert(
      defined(invoker.packaged_resources) ||
          defined(invoker.generated_header_dir),
      "hap_profile or generated_header_dir must be defined for compile_resources")
  _generate_resource = defined(invoker.packaged_resources)
  if (_generate_resource) {
    _packaged_resources = invoker.packaged_resources
  }
  _generate_header = defined(invoker.generated_header_dir)
  if (_generate_header) {
    _generated_header_file = invoker.generated_header_dir + "/ResourceTable.h"
  }
  action_with_pydeps(target_name) {
    forward_variables_from(invoker,
                           [
                             "meta_data",
                             "hap_profile",
                             "deps",
                           ])
    script = "//build/scripts/compile_resources.py"
    depfile = "$target_gen_dir/$target_name.d"
    if (ohos_indep_compiler_enable) {
      restool_path = "${prebuilts_sdk_dir}/toolchains/restool"
    } else {
      if (defined(deps)) {
        deps += [
          "//developtools/global_resource_tool:restool($host_toolchain)",
          "//developtools/global_resource_tool:restool_id_defined($host_toolchain)",
        ]
      } else {
        deps = [
          "//developtools/global_resource_tool:restool($host_toolchain)",
          "//developtools/global_resource_tool:restool_id_defined($host_toolchain)",
        ]
      }
      restool_path =
          get_label_info(
              "//developtools/global_resource_tool:restool($host_toolchain)",
              "root_out_dir") + "/developtools/global_resource_tool/restool"
    }
    _rebased_metadata = rebase_path(meta_data, root_build_dir)
    inputs = [
      meta_data,
      restool_path,
      hap_profile,
    ]
    args = [
      "--resources-dir=@FileArg($_rebased_metadata:root:resources)",
      "--depfile",
      rebase_path(depfile, root_build_dir),
      "--restool-path",
      rebase_path(restool_path, root_build_dir),
      "--hap-profile=@FileArg($_rebased_metadata:root:hap_profile)",
      "--app-profile=@FileArg($_rebased_metadata:root:app_profile)",
    ]
    outputs = []
    if (_generate_resource) {
      outputs += [ _packaged_resources ]
      args += [
        "--output-resources-zipfile",
        rebase_path(_packaged_resources, root_build_dir),
      ]
    }
    if (_generate_header) {
      outputs += [ _generated_header_file ]
      args += [
        "--output-header-file",
        rebase_path(_generated_header_file, root_build_dir),
      ]
    }
  }
}

template("package_app") {
  forward_variables_from(invoker, [ "testonly" ])
  assert(defined(invoker.hap_profile),
         "hap_profile must be defined for $target_name")
  assert(defined(invoker.hap_path), "hap_path must be defined for $target_name")
  action_with_pydeps(target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "external_deps",
                             "shared_libraries",
                             "hap_profile",
                             "hap_path",
                             "packaged_resources",
                             "packaged_js_assets",
                             "meta_data",
                             "private_key_path",
                             "signature_algorithm",
                             "certificate_profile",
                             "keystore_path",
                             "keystore_password",
                             "key_alias",
                             "certificate_file",
                             "install_module_info",
                             "enable_ark",
                             "build_mode",
                             "compatible_version",
                           ])
    script = "//build/scripts/hapbuilder.py"
    depfile = "$target_gen_dir/$target_name.d"
    _rebased_metadata = rebase_path(meta_data, root_build_dir)
    outputs = [ hap_path ]
    args = [
      "--depfile",
      rebase_path(depfile, root_build_dir),
      "--hap-profile=@FileArg($_rebased_metadata:root:hap_profile)",
      "--hapsigner",
      rebase_path(hapsigner, root_build_dir),
      "--hap-packing-tool",
      rebase_path(hap_packing_tool, root_build_dir),
      "--hap-path",
      rebase_path(hap_path, root_build_dir),
      "--packaged-resources",
      rebase_path(packaged_resources, root_build_dir),
      "--packaged-js-assets",
      rebase_path(packaged_js_assets, root_build_dir),
      "--assets=@FileArg($_rebased_metadata:root:assets)",
      "--app-profile=@FileArg($_rebased_metadata:root:app_profile)",
      "--build-mode",
      build_mode,
    ]

    inputs = [
      hap_profile,
      hapsigner,
      hap_packing_tool,
      packaged_js_assets,
      packaged_resources,
      meta_data,
    ]

    _private_key_path = default_hap_private_key_path
    if (defined(private_key_path)) {
      _private_key_path = private_key_path
    }
    _signature_algorithm = default_signature_algorithm
    if (defined(signature_algorithm)) {
      _signature_algorithm = signature_algorithm
    }
    _key_alias = default_key_alias
    if (defined(key_alias)) {
      _key_alias = key_alias
    }
    _keystore_path = default_keystore_path
    if (defined(keystore_path)) {
      _keystore_path = keystore_path
    }
    _keystore_password = default_keystore_password
    if (defined(keystore_password)) {
      _keystore_password = keystore_password
    }
    _certificate_file = default_hap_certificate_file
    if (defined(certificate_file)) {
      _certificate_file = certificate_file
    }

    inputs += [
      certificate_profile,
      _keystore_path,
      _certificate_file,
    ]
    _sign_hap_py_path = "//build/scripts/app_sign.py"
    if (defined(sign_hap_py_path) && defined(compatible_version)) {
      _sign_hap_py_path = sign_hap_py_path
    }

    args += [
      "--sign_hap_py_path",
      rebase_path(_sign_hap_py_path),
    ]
    if (defined(sign_hap_py_path)) {
      if (defined(compatible_version)) {
        _sign_compatible_version = compatible_version
        args += [
          "--sign_compatible_version",
          _sign_compatible_version,
        ]
      } else {
        _target_label = get_label_info(target_name, "label_no_toolchain")
        print(
            "warning: Please set compatible_version in ${_target_label} for remote sign")
      }
    }
    args += [
      "--private-key-path",
      _private_key_path,
      "--sign-algo",
      _signature_algorithm,
      "--certificate-profile",
      rebase_path(certificate_profile, root_build_dir),
      "--keyalias",
      _key_alias,
      "--keystore-path",
      rebase_path(_keystore_path, root_build_dir),
      "--keystorepasswd",
      _keystore_password,
      "--certificate-file",
      rebase_path(_certificate_file, root_build_dir),
    ]

    if (defined(shared_libraries)) {
      foreach(lib, shared_libraries) {
        _module_info = get_label_info(lib, "target_out_dir") + "/" +
                       get_label_info(lib, "name") + "_module_info.json"
        _rebased_module_info = rebase_path(_module_info, root_build_dir)
        args += [ "--dso=@FileArg($_rebased_module_info:source)" ]
      }
      if (is_ohos) {
        args += [
          "--ohos-app-abi",
          ohos_app_abi,
        ]
      }
    }

    if (defined(external_deps)) {
      foreach(lib, external_deps) {
        _module_info = get_label_info(lib, "target_out_dir") + "/" +
                       get_label_info(lib, "name") + "_module_info.json"
        _rebased_module_info = rebase_path(_module_info, root_build_dir)
        args += [ "--dso=@FileArg($_rebased_module_info:source)" ]
      }
      if (is_ohos) {
        args += [
          "--ohos-app-abi",
          ohos_app_abi,
        ]
      }
    }

    _test_target = defined(invoker.test_type) && invoker.test_type != "" && defined(testonly) && testonly

    if (defined(install_module_info)) {
      test_info = []
      if (_test_target) {
        if (test_label_type != "" && string_replace(test_label_type, invoker.test_type, "") != test_label_type) {
            test_info += [ install_module_info.module_def ]
        }
      }
      metadata = {
        install_modules = [ install_module_info ]
        test_list_info = test_info
      }
    }
    if (defined(enable_ark) && enable_ark) {
      if (ohos_indep_compiler_enable) {
        _js2abc_js =
            "${prebuilts_sdk_dir}/ets/build-tools/ets-loader/bin/ark/ts2abc.js"
      } else {
        _ark_deps = [
          "//arkcompiler/ets_frontend/es2panda:es2abc_js_file($host_toolchain)",
        ]
        external_deps = [ "ets_frontend:es2panda($host_toolchain)" ]
        if (defined(deps)) {
          deps += _ark_deps
        } else {
          deps = _ark_deps
        }
        _js2abc_js = get_label_info(
                         "//arkcompiler/ets_frontend/es2panda:es2abc_js_file($host_toolchain)",
                         "target_out_dir") + "/ts2abc.js"
      }
      args += [
        "--nodejs-path",
        rebase_path(nodejs, root_build_dir),
        "--js2abc-js",
        rebase_path(_js2abc_js, root_build_dir),
        "--enable-ark",
      ]
      inputs += [
        nodejs,
        _js2abc_js,
      ]
    }
  }
}

template("compile_js_assets") {
  forward_variables_from(invoker, [ "testonly" ])
  assert(defined(invoker.meta_data) && defined(invoker.packaged_js_assets),
         "meta_data and packaged_js_assets must be for compile_js_assets")

  _packaged_js_assets = invoker.packaged_js_assets
  action_with_pydeps(target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "meta_data",
                             "hap_profile",
                             "build_mode",
                             "js2abc",
                             "ets2abc",
                             "main_target_name",
                           ])
    script = "//build/scripts/build_js_assets.py"
    depfile = "$target_gen_dir/$target_name.d"
    outputs = [ _packaged_js_assets ]

    _rebased_metadata = rebase_path(meta_data, root_build_dir)

    if (!defined(deps)) {
      deps = []
    }
    if (ohos_indep_compiler_enable) {
      _ace_loader_home = "${prebuilts_sdk_dir}/js/build-tools/ace-loader"
      _ets_loader_home = "${prebuilts_sdk_dir}/ets/build-tools/ets-loader/"
    } else {
      deps += [
        "//arkcompiler/ets_frontend/es2panda:build_es2abc_for_hap($host_toolchain)",
        "//developtools/ace_js2bundle:ace_loader_ark_hap",
        "//third_party/parse5:parse5_ark_hap",
        "//third_party/weex-loader:weex_loader_ark_hap",
      ]
      external_deps = [ "ace_ets2bundle:ets_loader_ark_hap" ]
      _ace_loader_home =
          get_label_info("//developtools/ace_js2bundle:ace_loader_node_modules",
                         "target_out_dir") + "/ace_loader_ark"
      _ets_loader_home =
          get_label_info(
              "//developtools/ace_ets2bundle:ets_loader_node_modules",
              "target_out_dir") + "/ets_loader_ark"
    }

    _webpack_config_js = "${_ace_loader_home}/webpack.rich.config.js"
    _webpack_config_ets = "${_ets_loader_home}/webpack.config.js"
    _webpack_js = "${_ace_loader_home}/node_modules/webpack/bin/webpack.js"
    _webpack_ets = "${_ets_loader_home}/node_modules/webpack/bin/webpack.js"
    _manifest_file_path = "${target_gen_dir}/manifest_file"

    inputs = [
      meta_data,
      nodejs,
    ]

    args = [
      "--js-assets-dir=@FileArg($_rebased_metadata:root:js_assets)",
      "--ets-assets-dir=@FileArg($_rebased_metadata:root:ets_assets)",
      "--js-forms-dir=@FileArg($_rebased_metadata:root:js_forms)",
      "--testrunner-dir=@FileArg($_rebased_metadata:root:testrunner)",
      "--output",
      rebase_path(_packaged_js_assets, root_build_dir),
      "--depfile",
      rebase_path(depfile, root_build_dir),
      "--nodejs-path",
      rebase_path(nodejs, root_build_dir),
      "--webpack-js",
      rebase_path(_webpack_js, root_build_dir),
      "--webpack-ets",
      rebase_path(_webpack_ets, root_build_dir),
      "--webpack-config-js",
      rebase_path(_webpack_config_js, root_build_dir),
      "--webpack-config-ets",
      rebase_path(_webpack_config_ets, root_build_dir),
      "--build-mode",
      build_mode,
      "--ace-loader-home",
      rebase_path(_ace_loader_home, root_build_dir),
      "--ets-loader-home",
      rebase_path(_ets_loader_home, root_build_dir),
      "--hap-profile=@FileArg($_rebased_metadata:root:hap_profile)",
      "--app-profile=@FileArg($_rebased_metadata:root:app_profile)",
      "--manifest-file-path",
      rebase_path(_manifest_file_path, root_build_dir),
    ]
    if (defined(testonly) && testonly == true) {
      _js_sources_file = target_gen_dir + "/$main_target_name.sources"
      args += [
        "--js-sources-file",
        rebase_path(_js_sources_file, root_build_dir),
      ]
      outputs += [ _js_sources_file ]
    }

    if (js2abc || ets2abc) {
      if (ohos_indep_compiler_enable) {
        _es2abc_dir = "${prebuilts_sdk_dir}/js/build-tools/ace-loader/bin/ark"
      } else {
        _es2abc_dir = get_label_info("ets_frontend:es2panda($host_toolchain)",
                                     "target_out_dir")
      }
      if (ets2abc) {
        args += [ "--ets2abc" ]
      } else if (js2abc) {
        args += [ "--js2abc" ]
      }
      args += [
        "--ark-es2abc-dir",
        rebase_path(_es2abc_dir, root_build_dir),
      ]
    }

    if (defined(hap_profile)) {
      inputs += [ hap_profile ]
    }
  }
}

template("app_sign") {
  forward_variables_from(invoker, [ "testonly" ])
  sign_variables = [
    "deps",
    "private_key_path",
    "signature_algorithm",
    "certificate_profile",
    "keystore_password",
    "key_alias",
    "certificate_file",
    "keystore_path",
    "unsigned_hap_path_list",
    "hap_out_dir",
    "hap_name",
    "install_module_info",
    "compatible_version",
  ]
  if (defined(invoker.hap_list)) {
    sign_variables += [ "hap_list" ]
  }
  action(target_name) {
    forward_variables_from(invoker, sign_variables)
    _sign_hap_py_path = "//build/scripts/app_sign.py"
    if (defined(sign_hap_py_path) && defined(compatible_version)) {
      _sign_hap_py_path = sign_hap_py_path
    }
    script = _sign_hap_py_path
    _private_key_path = default_hap_private_key_path
    if (defined(private_key_path)) {
      _private_key_path = private_key_path
    }
    _key_alias = default_key_alias
    if (defined(key_alias)) {
      _key_alias = key_alias
    }
    _signature_algorithm = default_signature_algorithm
    if (defined(signature_algorithm)) {
      _signature_algorithm = signature_algorithm
    }
    _keystore_path = default_keystore_path
    if (defined(keystore_path)) {
      _keystore_path = keystore_path
    }
    _certificate_file = default_hap_certificate_file
    if (defined(certificate_file)) {
      _certificate_file = certificate_file
    }
    _keystore_password = default_keystore_password
    if (defined(keystore_password)) {
      _keystore_password = keystore_password
    }
    if (defined(certificate_profile)) {
      _certificate_profile = certificate_profile
    }

    inputs = [
      hapsigner,
      certificate_profile,
      _keystore_path,
      _certificate_file,
    ]

    outputs = [ "${target_out_dir}/${target_name}.stamp" ]

    args = [
      "--keyPwd",
      _private_key_path,
      "--sign-algo",
      _signature_algorithm,
      "--profileFile",
      rebase_path(_certificate_profile, root_build_dir),
      "--keyalias",
      _key_alias,
      "--keystoreFile",
      rebase_path(_keystore_path, root_build_dir),
      "--keystorePwd",
      _keystore_password,
      "--certificate-file",
      rebase_path(_certificate_file, root_build_dir),
      "--hapsigner",
      rebase_path(hapsigner, root_build_dir),
      "--unsigned-hap-path-list",
      rebase_path(unsigned_hap_path_list, root_build_dir),
      "--hap-out-dir",
      rebase_path(hap_out_dir, root_build_dir),
      "--hap-name",
      hap_name,
    ]
    if (defined(invoker.hap_list)) {
      args += [
        "--hap-list",
        rebase_path(hap_list, root_build_dir),
      ]
    }

    if (defined(sign_hap_py_path)) {
      if (defined(compatible_version)) {
        _sign_compatible_version = compatible_version
        args += [
          "--compatible_version",
          _sign_compatible_version,
        ]
      } else {
        _target_label = get_label_info(target_name, "label_no_toolchain")
        print(
            "warning: Please set compatible_version in ${_target_label} for remote sign")
      }
    }

    _test_target = defined(invoker.test_type) && invoker.test_type != "" && defined(testonly) && testonly

    if (defined(install_module_info)) {
      test_info = []
      if (_test_target) {
        if (test_label_type != "" && string_replace(test_label_type, invoker.test_type, "") != test_label_type) {
            test_info += [ install_module_info.module_def ]
        }
      }
      metadata = {
        install_modules = [ install_module_info ]
        test_list_info = test_info
      }
    }
  }
}

template("compile_app") {
  forward_variables_from(invoker,
                         [
                           "testonly",
                           "nodejs_path",
                         ])
  if (defined(nodejs_path) && nodejs_path != "") {
    _nodejs = nodejs_path
  } else {
    if (host_os == "mac") {
      _nodejs = "//prebuilts/build-tools/common/nodejs/node-${default_hvigor_nodejs_version}-darwin-x64/bin/node"
    } else if (host_os == "linux" && host_os == "arm64") {
      _nodejs = "//prebuilts/build-tools/common/nodejs/node-${default_hvigor_nodejs_version}-linux-aarch64/bin/node"
    } else {
      _nodejs = "//prebuilts/build-tools/common/nodejs/node-${default_hvigor_nodejs_version}-${host_os}-x64/bin/node"
    }
  }

  action(target_name) {
    forward_variables_from(invoker,
                           [
                             "deps",
                             "cwd",
                             "build_mode",
                             "build_profile",
                             "app_profile",
                             "hap_profile",
                             "build_level",
                             "assemble_type",
                             "sdk_home",
                             "unsigned_hap_path_list",
                             "system_lib_deps",
                             "hap_out_dir",
                             "hap_name",
                             "install_module_info",
                             "test_hap",
                             "test_module",
                             "module_libs_dir",
                             "sdk_type_name",
                             "build_modules",
                             "hvigor_home",
                             "ohos_test_coverage",
                             "product",
                           ])
    script = "//build/scripts/compile_app.py"
    outputs = [ unsigned_hap_path_list ]

    args = [
      "--nodejs",
      rebase_path(_nodejs, root_build_dir),
      "--cwd",
      rebase_path(cwd, root_build_dir),
      "--build-profile",
      rebase_path(build_profile, root_build_dir),
      "--sdk-home",
      rebase_path(sdk_home),
      "--output-file",
      rebase_path(unsigned_hap_path_list, root_build_dir),
      "--ohpm-registry",
      ohpm_registry,
      "--product",
      product,
      "--host-os",
      host_os
    ]

    if (defined(ohos_test_coverage) && ohos_test_coverage) {
      args += [ "--ohos-test-coverage" ]
    }

    if (defined(hvigor_home) && hvigor_home != "") {
      args += [
        "--hvigor-home",
        rebase_path(hvigor_home, root_build_dir),
      ]
    }

    if (defined(build_mode) && build_mode == "debug") {
      args += [ "--enable-debug" ]
    }

    if (defined(test_hap) && test_hap) {
      args += [ "--test-hap" ]
    }

    if (defined(test_module) && test_module != "") {
      args += [
        "--test-module",
        test_module,
      ]
    }
    if (defined(module_libs_dir) && module_libs_dir != "") {
      args += [
        "--module-libs-dir",
        module_libs_dir,
      ]
    }
    if (defined(build_level) && build_level != "") {
      args += [
        "--build-level",
        build_level,
      ]
    }
    if (defined(assemble_type) && assemble_type != "") {
      args += [
        "--assemble-type",
        assemble_type,
      ]
    }
    if (defined(system_lib_deps)) {
      args += [ "--system-lib-module-info-list" ]
      foreach(_lib_deps, system_lib_deps) {
        _lib_out_name = get_label_info(_lib_deps, "name")
        _lib_out_dir = get_label_info(_lib_deps, "target_out_dir")
        args +=
            [ rebase_path("${_lib_out_dir}/${_lib_out_name}_module_info.json",
                          root_build_dir) ]
      }

      if (is_ohos) {
        args += [
          "--ohos-app-abi",
          ohos_app_abi,
        ]
      }
    }
    if (defined(sdk_type_name) && sdk_type_name != []) {
      args += [ "--sdk-type-name" ]
      args += sdk_type_name
    }
    if (defined(build_modules) && build_modules != []) {
      args += [ "--build-modules" ]
      args += build_modules
    }
    if (use_hvigor_cache) {
      args += [ "--use-hvigor-cache" ]
    }
    if (hvigor_obfuscation) {
      args += [ "--hvigor-obfuscation" ]
    }
    if (defined(install_module_info)) {
      metadata = {
        install_modules = [ install_module_info ]
      }
    }
    if (defined(target_app_dir) && target_app_dir != "") {
      args += [
        "--target-out-dir",
        rebase_path(root_out_dir),
        "--target-app-dir",
        target_app_dir,
      ]
    }
    if (ohos_app_enable_asan) {
      args += [ "--ohos-app-enable-asan" ]
    } else if (ohos_app_enable_tsan) {
      args += [ "--ohos-app-enable-tsan" ]
    } else if (ohos_app_enable_ubsan) {
      args += [ "--ohos-app-enable-ubsan" ]
    }
  }
}