# Copyright 2023 The Chromium Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Android module to prepare APKs and emulators to run webdriver-based tests.
"""

import re
import os
import subprocess
import sys

from pkg_resources import packaging
from typing import List, Optional

from chrome.test.variations.test_utils import SRC_DIR

# The root for the module pylib/android is under build/android.
sys.path.append(os.path.join(SRC_DIR, 'build', 'android'))

# This import adds `devil` to `sys.path`.
import devil_chromium

from devil.android import apk_helper
from devil.android import device_utils
from devil.android import forwarder
from devil.android.sdk import adb_wrapper
from pylib.local.emulator import avd

_INSTALLER_SCRIPT_PY = os.path.join(
  SRC_DIR, 'clank', 'bin', 'utils', 'installer_script_wrapper.py')


def _package_name(channel: str):
  if channel in ('beta', 'dev', 'canary'):
    return f'com.chrome.{channel}'
  return 'com.android.chrome'


def _is_require_signed(channel: str) -> bool:
  """Check if we need to install a signed build."""
  # The stable build has the same package name as prebuilt one, in order
  # to avoid the signature mismatch, we need to install the one with the
  # same signed build.
  return channel == 'stable'


def install_chrome(channel: str, device: device_utils.DeviceUtils) -> str:
  """Installs Chrome to the device and returns the package name."""
  args = [
    _INSTALLER_SCRIPT_PY, f'--product=chrome',
    f'--channel={channel}', f'--serial={device.serial}',
    f'--adb={adb_wrapper.AdbWrapper.GetAdbPath()}',
  ]
  args.append('--signed' if _is_require_signed(channel) else '--unsigned')
  subprocess.check_call(args=args)
  return _package_name(channel)


def install_webview(
  channel: str,
  device: device_utils.DeviceUtils
  ) -> packaging.version.Version:
  """Installs Webview to the device and returns the installed version."""
  args = [
    _INSTALLER_SCRIPT_PY, f'--product=webview',
    f'--channel={channel}', f'--serial={device.serial}',
    f'--adb={adb_wrapper.AdbWrapper.GetAdbPath()}',
  ]
  args.append('--signed' if _is_require_signed(channel) else '--unsigned')
  subprocess.check_call(args=args)

  version_regex = r'\s*Preferred WebView package[^:]*[^\d]*([^\)]+)'
  version_output = device.RunShellCommand(['dumpsys' ,'webviewupdate'])
  version = [
    m.group(1)
    for line in version_output if (m := re.match(version_regex, line))
  ]
  return packaging.version.parse(version[0]) if version else None


def _forward_port(device: device_utils.DeviceUtils,
                  ports: Optional[List[int]] = None):
  # Ideally, we would dynamically allocate ports from the device, and
  # remember the mapping here, it requires how the client redirects ports.
  # Since we currently only allocate ports from a user space whose value is
  # always 3xxxx and above, there is a very rare case to cause issues here.
  # It is possible that the port is already used on the device, however,
  # the likelihood is small, and we will fix once it shows a problem.
  if ports:
    forwarder.Forwarder.Map([(port, port) for port in ports], device)


def launch_emulator(avd_config: str,
                    emulator_window: bool,
                    ports: Optional[List[int]] = None) -> avd._AvdInstance:
  """Launches the emulator and forwards ports from device to host."""
  avd_config = avd.AvdConfig(avd_config)
  avd_config.Install()

  instance = avd_config.CreateInstance()
  instance.Start(writable_system=True,
                 window=emulator_window,
                 require_fast_start=True)

  _forward_port(instance.device, ports)

  return instance
