# Copyright 2015 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import(
    "//chrome/browser/resources/chromeos/accessibility/tools/generate_message_formatting_data.gni")
import(
    "//chrome/browser/resources/chromeos/accessibility/tools/run_jsbundler.gni")
import("//chrome/common/features.gni")
import("//chrome/test/base/ash/js2gtest.gni")
import("//testing/test.gni")
import("//tools/typescript/ts_library.gni")
import("//ui/webui/resources/tools/bundle_js.gni")
import("//ui/webui/resources/tools/minify_js.gni")

group("build") {
  deps = [
    ":chromevox_phonetic_dictionaries_js",
    ":copied_files",
    "//third_party/liblouis",
  ]
}

chromevox_out_dir =
    "$root_out_dir/resources/chromeos/accessibility/chromevox/mv3"

# Directory where typescript build will occur.
ts_build_staging_dir = "$target_gen_dir/ts_build_staging"

tsc_out_dir = "$target_gen_dir/tsc"

# Location of common typescript output.
common_tsc_dir =
    "$root_gen_dir/chrome/browser/resources/chromeos/accessibility/common/tsc"

# Messageformat third_party directory.
messageformat_dir = "//third_party/node/node_modules/messageformat/lib/"

# Location of sre dependency.
sre_browser_file = "//third_party/chromevox/third_party/sre/sre_browser.js"

# List of all modules that are included in one or more of the production
# chromevox scripts.
#
# TS files to compile.
ts_modules = [
  "background/abstract_earcons.ts",
  "background/abstract_tts.ts",
  "background/auto_scroll_handler.ts",
  "background/background.ts",
  "background/braille/braille_background.ts",
  "background/braille/braille_captions_background.ts",
  "background/braille/braille_command_handler.ts",
  "background/braille/braille_display_manager.ts",
  "background/braille/braille_input_handler.ts",
  "background/braille/braille_interface.ts",
  "background/braille/braille_key_event_rewriter.ts",
  "background/braille/braille_translator.ts",
  "background/braille/braille_translator_manager.ts",
  "background/braille/cursor_dots.ts",
  "background/braille/expanding_braille_translator.ts",
  "background/braille/composition_candidate_provider.ts",
  "background/braille/liblouis.ts",
  "background/braille/pan_strategy.ts",
  "background/braille/spans.ts",
  "background/braille/tenji_translator.ts",
  "background/braille/wasm_kana_kanji_provider.ts",
  "background/captions_handler.ts",
  "background/chromevox.ts",
  "background/chromevox_range.ts",
  "background/chromevox_state.ts",
  "background/color.ts",
  "background/console_tts.ts",
  "background/download_handler.ts",
  "background/earcons.ts",
  "background/editing/editable_line.ts",
  "background/editing/editable_text.ts",
  "background/editing/editable_text_base.ts",
  "background/editing/editing_range_observer.ts",
  "background/editing/intent_handler.ts",
  "background/editing/rich_editable_text.ts",
  "background/editing/text_edit_handler.ts",
  "background/editing/typing_echo.ts",
  "background/event_source.ts",
  "background/event/base_automation_handler.ts",
  "background/event/desktop_automation_handler.ts",
  "background/event/desktop_automation_interface.ts",
  "background/event/focus_automation_handler.ts",
  "background/event/media_automation_handler.ts",
  "background/event/page_load_sound_handler.ts",
  "background/event/pointer_handler.ts",
  "background/event/range_automation_handler.ts",
  "background/find_handler.ts",
  "background/focus_bounds.ts",
  "background/forced_action_path.ts",
  "background/injected_script_loader.ts",
  "background/input/background_keyboard_handler.ts",
  "background/input/clipboard_handler.ts",
  "background/input/command_handler_interface.ts",
  "background/input/command_handler.ts",
  "background/input/gesture_command_handler.ts",
  "background/input/gesture_interface.ts",
  "background/input/smart_sticky_mode.ts",
  "background/live_regions.ts",
  "background/logging/event_stream_logger.ts",
  "background/logging/log_manager.ts",
  "background/logging/log_url_watcher.ts",
  "background/logging/log_store.ts",
  "background/math_handler.ts",
  "background/output/braille_output.ts",
  "background/output/output.ts",
  "background/output/output_ancestry_info.ts",
  "background/output/output_format_parser.ts",
  "background/output/output_format_tree.ts",
  "background/output/output_formatter.ts",
  "background/output/output_role_info.ts",
  "background/output/output_interface.ts",
  "background/output/output_logger.ts",
  "background/output/output_rules.ts",
  "background/output/output_types.ts",
  "background/panel/i_search.ts",
  "background/panel/i_search_handler.ts",
  "background/panel/panel_background.ts",
  "background/panel/panel_node_menu_background.ts",
  "background/prefs.ts",
  "background/primary_tts.ts",
  "background/tts_background.ts",
  "background/tts_interface.ts",
  "chromevox_loader.ts",
  "common/background_bridge.ts",
  "common/braille/braille_command_data.ts",
  "common/braille/braille_key_types.ts",
  "common/braille/braille_table.ts",
  "common/braille/nav_braille.ts",
  "services/tenji/sandboxed_tenji_wrapper.ts",
  "common/bridge_constants.ts",
  "common/command.ts",
  "common/command_store.ts",
  "common/custom_automation_event.ts",
  "common/earcon_id.ts",
  "common/event_source_type.ts",
  "common/gesture.ts",
  "common/gesture_command_data.ts",
  "common/internal_key_event.ts",
  "common/keyboard_handler.ts",
  "common/key_map.ts",
  "common/key_sequence.ts",
  "common/key_util.ts",
  "common/learn_mode_bridge.ts",
  "common/locale_output_helper.ts",
  "common/log_types.ts",
  "common/msgs.ts",
  "common/offscreen_bridge.ts",
  "common/offscreen_bridge_constants.ts",
  "common/panel_bridge.ts",
  "common/panel_command.ts",
  "common/role_type.ts",
  "common/panel_menu_data.ts",
  "common/permission_checker.ts",
  "common/settings_manager.ts",
  "common/spannable.ts",
  "common/tree_dumper.ts",
  "common/tts_types.ts",
  "learn_mode/learn_mode.ts",
  "log_page/log.ts",
  "log_page/log_loader.ts",
  "offscreen/earcon_engine.ts",
  "offscreen/offscreen.ts",
  "offscreen/liblouis_worker.ts",
  "offscreen/tenji_worker.ts",
  "panel/i_search_ui.ts",
  "panel/menu_manager.ts",
  "panel/menu_manager_with_test_endpoints.ts",
  "panel/panel.ts",
  "panel/panel_captions.ts",
  "panel/panel_interface.ts",
  "panel/panel_menu.ts",
  "panel/panel_menu_item.ts",
  "panel/panel_mode.ts",

  # TODO(crbug.com/388867840): Move ja_phonetic_*.ts to the background
  # directory (follow same structure as mv2).
  "third_party/tamachiyomi/ja_phonetic_data.ts",
  "third_party/tamachiyomi/ja_phonetic_map.ts",
]

# ES6 modules.
js_modules = [
  "background/automation_object_constructor_installer.js",
  "background/composite_tts.js",
  "background/phonetic_data.js",
]

copied_ts_modules = [ "ash/common/braille_table.ts" ]

copy("stage_ash_braille_table") {
  sources = [ "//ash/webui/common/resources/accessibility/braille_table.ts" ]
  outputs = [ "$ts_build_staging_dir/ash/common/braille_table.ts" ]
}

# Root dir must be the parent directory so it can reach common/.
ts_library("build_ts") {
  root_dir = "$ts_build_staging_dir"
  out_dir = tsc_out_dir

  deps = [ "../../common:build_ts" ]

  extra_deps = [
    #copied files
    ":stage_ash_braille_table",
    ":stage_ts_build",
    ":stage_ts_build_sre",
  ]

  definitions = [
    "//tools/typescript/definitions/chrome_event.d.ts",
    "//tools/typescript/definitions/context_menus.d.ts",
    "//tools/typescript/definitions/metrics_private.d.ts",
    "../../definitions/windows.d.ts",
    "../../definitions/accessibility_private_mv2.d.ts",
    "../../definitions/audio.d.ts",
    "../../definitions/automation.d.ts",
    "../../definitions/braille_display_private_mv2.d.ts",
    "../../definitions/chromeos_info_private.d.ts",
    "../../definitions/clipboard_mv2.d.ts",
    "../../definitions/downloads.d.ts",
    "../../definitions/extension_types.d.ts",
    "../../definitions/extensions.d.ts",
    "../../definitions/i18n.d.ts",
    "../../definitions/login_state.d.ts",
    "../../definitions/offscreen.d.ts",
    "../../definitions/runtime.d.ts",
    "../../definitions/settings_private_mv2.d.ts",
    "../../definitions/storage_mv2.d.ts",
    "../../definitions/tabs.d.ts",
    "../../definitions/tts.d.ts",
  ]

  path_mappings = [
    "/common/*|" + rebase_path("$common_tsc_dir/*", target_gen_dir),
    "/chromevox/mv3/third_party/messageformat/messageformat.rollup.js|" +
        rebase_path("$messageformat_dir/messageformat.d.ts", target_gen_dir),

    # Point the TS compiler to the copied version of sre_browser.js.
    "/chromevox/mv3/third_party/sre/sre_browser.js|" +
        rebase_path("$ts_build_staging_dir/third_party/sre/sre_browser.js",
                    target_gen_dir),

    # Point to the copied version of ash's braille_table.ts.
    "/chromevox/mv3/ash/common/braille_table.js|" +
        rebase_path("$ts_build_staging_dir/ash/common/braille_table.ts",
                    target_gen_dir),
  ]

  in_files = ts_modules + js_modules + copied_ts_modules

  tsconfig_base = "../../tsconfig.base.json"
}

generate_message_formatting_data("i18n_data") {
  inputs = [ "//third_party/cldr/src/common/supplemental/plurals.xml" ]
  output_dir = "$chromevox_out_dir"
}

# Instead of setting up one copy target for each subdirectory, use a script
# to copy all files.
# TODO(crbug.com/388867840): Use bundle_js and minify_js for the background and
# panel scripts, similar to what is done for mv2.
run_jsbundler("copied_files") {
  mode = "copy"
  dest_dir = chromevox_out_dir
  deps = [
    ":build_ts",
    ":copy_sre",
    ":minify_js_messageformat",
    "../../common:build_ts",
    "../../common:copied_files",
  ]

  clear_dest_dirs = [
    "background",
    "common",
    "earcons",
    "images",
    "injected",
    "learn_mode",
    "log_page",
    "panel",
    "tutorial",
  ]

  sources = [
    "images/chromevox.svg",
    "images/close-36.png",
    "images/close-hover-36.png",
    "images/options-36.png",
    "images/options-hover-36.png",
    "images/triangle-6.png",
    "injected/cvox_gdocs_script.js",
    "learn_mode/learn_mode.html",
    "log_page/log.css",
    "log_page/log.html",
    "offscreen/offscreen.html",
    "panel/panel.css",
    "panel/panel.html",
    "services/tenji/sandboxed_tenji_wrapper.html",
    "tutorial/practice_areas/jump_commands.html",
    "tutorial/practice_areas/selects.html",
  ]
  sources += filter_include(get_target_outputs(":build_ts"), [ "*.js" ])

  rewrite_rules = [
    rebase_path("$tsc_out_dir", root_build_dir) + ":",
    rebase_path(".", root_build_dir) + ":",
  ]
}

# Copy all JS and TS sources to a staging folder. All generated TS/JS files
# will also be copied into this folder, which will allow us to support a TS
# build that uses both checked-in and generated files.
copy("stage_ts_build") {
  sources = js_modules + ts_modules
  outputs = [ "$ts_build_staging_dir/{{source_target_relative}}" ]
}

template("generate_deps_js") {
  if (defined(invoker.rewrite_rules)) {
    rewrite_rules = invoker.rewrite_rules
  } else {
    rewrite_rules = []
  }
  action(target_name) {
    if (defined(invoker.testonly)) {
      testonly = invoker.testonly
    }
    script = "//chrome/browser/resources/chromeos/accessibility/tools/generate_deps.py"
    inputs = jsbundler_modules
    sources = invoker.sources
    outputs = [ invoker.output_file ]
    args = [
      "-o",
      rebase_path(invoker.output_file, root_build_dir),
    ]
    foreach(rule, rewrite_rules) {
      args += [
        "-w",
        rule,
      ]
    }
    args += rebase_path(sources, root_build_dir)
    if (defined(invoker.deps)) {
      deps = invoker.deps
    }
  }
}

action("chromevox_phonetic_dictionaries_js") {
  script = "//chrome/browser/resources/chromeos/accessibility/tools/phonetic_dictionaries.py"
  src_dir = [ "$root_out_dir/resources/chromeos/accessibility/_locales" ]
  output_file = "$chromevox_out_dir/phonetic_dictionaries.js"
  outputs = [ output_file ]
  deps = [
    "//chrome/browser/resources/chromeos/accessibility:accessibility_strings",
  ]
  args = [
           "-o",
           rebase_path(output_file, root_build_dir),
         ] + rebase_path(src_dir, root_build_dir)
}

source_set("browser_tests") {
  testonly = true
  assert(enable_extensions)

  deps = [ ":chromevox_extension_js_tests" ]

  # TODO(jamescook): Figure out which of these are really necessary.
  data = [
    "$root_out_dir/chrome_100_percent.pak",
    "$root_out_dir/chrome_200_percent.pak",
    "$root_out_dir/locales/en-US.pak",
    "$root_out_dir/locales/fr.pak",
    "$root_out_dir/resources.pak",
    "$root_out_dir/resources/chromeos/accessibility/chromevox/",
    "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/",

    "//chrome/browser/resources/chromeos/accessibility/chromevox/",
    "//chrome/browser/resources/chromeos/accessibility/common",
    "//third_party/chromevox/",
  ]
  data += js2gtest_js_libraries
}

action("chromevox_test_messages_js") {
  script = "//chrome/browser/resources/chromeos/accessibility/tools/generate_test_messages.py"
  sources = [ "$root_out_dir/resources/chromeos/accessibility/_locales/en/messages.json.gz" ]
  output_file = "$root_out_dir/test_data/chrome/browser/resources/chromeos/accessibility/chromevox/mv3/host/testing/test_messages.js"
  outputs = [ output_file ]
  deps = [
    "//chrome/browser/resources/chromeos/accessibility:accessibility_strings",
  ]
  args = [
           "-o",
           rebase_path(output_file, root_build_dir),
         ] + rebase_path(sources, root_build_dir)
}

chromevox_test_modules = get_target_outputs(":chromevox_test_messages_js")

generate_deps_js("chromevox_test_deps_js") {
  sources = chromevox_test_modules
  output_file = "$target_gen_dir/test_deps.js"
  rewrite_rules = [
    rebase_path("//", root_build_dir) + ":",
    rebase_path("$root_out_dir/test_data", root_build_dir) + ":",
  ]
  deps = [ ":chromevox_test_messages_js" ]
}

# These tests need a full extension renderer.
js2gtest("chromevox_extension_js_tests") {
  test_type = "extension"
  sources = [
    "background/auto_scroll_handler_test.js",
    "background/background_test.js",
    "background/braille/braille_captions_background_test.js",
    "background/braille/braille_display_manager_test.js",
    "background/braille/braille_input_handler_test.js",
    "background/braille/braille_test.js",
    "background/braille/braille_translator_manager_test.js",
    "background/braille/liblouis_test.js",
    "background/captions_handler_test.js",
    "background/chromevox_range_test.js",
    "background/color_test.js",
    "background/download_handler_test.js",
    "background/editing/editing_test.js",
    "background/editing/intent_handler_test.js",
    "background/event/desktop_automation_handler_test.js",
    "background/forced_action_path_test.js",
    "background/input/keyboard_handler_test.js",
    "background/input/smart_sticky_mode_test.js",
    "background/live_regions_test.js",
    "background/logging/log_store_test.js",
    "background/math_handler_test.js",
    "background/output/output_test.js",
    "background/panel/i_search_test.js",
    "background/panel/panel_background_test.js",
    "background/panel/panel_node_menu_background_test.js",
    "background/settings_test.js",
    "background/tts_background_test.js",
    "common/braille/braille_command_data_test.js",
    "common/braille/braille_table_test.js",
    "common/locale_output_helper_test.js",
    "common/settings_manager_test.js",
    "learn_mode/learn_mode_test.js",
    "panel/menu_manager_test.js",
    "panel/panel_test.js",
    "panel/panel_test_base.js",
    "panel/tutorial_test.js",
  ]

  # These tests need support for async/await (b/317173285).
  sources += [
    "background/braille/expanding_braille_translator_test.js",
    "background/braille/pan_strategy_test.js",
    "background/braille/tenji_translator_test.js",
    "background/editing/editable_text_test.js",
    "background/phonetic_data_test.js",
    "common/key_sequence_test.js",
    "common/spannable_test.js",
    "services/tenji/sandboxed_tenji_wrapper_test.js",
    "testing/mock_feedback_test.js",
  ]

  gen_include_files = [
    "../../common/testing/accessibility_test_base.js",
    "../../common/testing/assert_additions.js",
    "../../common/testing/callback_helper.js",
    "../../common/testing/documents.js",
    "../../common/testing/e2e_test_base.js",
    "testing/chromevox_e2e_test_base.js",
    "testing/mock_feedback.js",
  ]

  # The test base classes generate C++ code with these deps.
  deps = [
    "//ash",
    "//base",
    "//chrome/browser/ash/accessibility",
    "//chrome/browser/ash/system_web_apps",
    "//chrome/common",
  ]
  test_deps_js_outputs = get_target_outputs(":chromevox_test_deps_js")
  deps_js = test_deps_js_outputs[0]
  deps += [ ":chromevox_test_deps_js" ]
  defines = [ "HAS_OUT_OF_PROC_TEST_RUNNER" ]
}

bundle_js("bundle_js_messageformat") {
  visibility = [ ":minify_js_messageformat" ]

  host = "_ignored_"
  input = rebase_path("$messageformat_dir", root_build_dir)
  js_module_in_files = [ "messageformat.js" ]
  out_folder = "$target_gen_dir/messageformat"
}

minify_js("minify_js_messageformat") {
  visibility = [ ":copied_files" ]

  deps = [ ":bundle_js_messageformat" ]
  in_folder = "$target_gen_dir/messageformat"
  in_files = [ "messageformat.rollup.js" ]
  out_folder = "$chromevox_out_dir/third_party/messageformat/"
}

# Copy sre_browser.js to the staging directory so that it can be used at build
# time.
copy("stage_ts_build_sre") {
  sources = [ "$sre_browser_file" ]
  outputs = [ "$ts_build_staging_dir/third_party/sre/sre_browser.js" ]
}

# Copy sre_browser.js to chromevox_out_dir so that it can be used at runtime.
copy("copy_sre") {
  sources = [ "$sre_browser_file" ]
  outputs = [ "$chromevox_out_dir/third_party/sre/sre_browser.js" ]
}
