#
# Copyright 2017 The Cobalt Authors. All Rights Reserved.
#
# 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.
#
"""Android implementation of Starboard launcher abstraction."""

import os
import re
import socket
import subprocess
import sys
import threading
import time
from six.moves import queue

from starboard.android.shared.sdk_utils import SDK_PATH
from starboard.tools import abstract_launcher

_APP_PACKAGE_NAME = 'dev.cobalt.coat'

_APP_START_INTENT = 'dev.cobalt.coat/dev.cobalt.app.MainActivity'

# Matches an "adb shell am monitor" error line.
_RE_ADB_AM_MONITOR_ERROR = re.compile(r'\*\* ERROR')

# String added to queue to indicate process has crashed
_QUEUE_CODE_CRASHED = 'crashed'

# How long to keep logging after a crash in order to emit the stack trace.
_CRASH_LOG_SECONDS = 1.0

_RUNTIME_PERMISSIONS = [
    'android.permission.GET_ACCOUNTS',
    'android.permission.RECORD_AUDIO',
]


def TargetOsPathJoin(*path_elements):
  """os.path.join for the target (Android)."""
  return '/'.join(path_elements)


def CleanLine(line):
  """Removes trailing carriages returns from ADB output."""
  return line.replace('\r', '')


class StepTimer(object):
  """Class for timing how long install/run steps take."""

  def __init__(self, step_name):
    self.step_name = step_name
    self.start_time = time.time()
    self.end_time = None

  def Stop(self):
    if self.start_time is None:
      sys.stderr.write('Cannot stop timer; not started\n')
    else:
      self.end_time = time.time()
      total_time = self.end_time - self.start_time
      sys.stderr.write(f'Step "{self.step_name}" took {total_time} seconds.\n')


class AdbCommandBuilder(object):
  """Builder for 'adb' commands."""

  def __init__(self, adb, device_id=None):
    self.adb = adb
    self.device_id = device_id

  def Build(self, *args):
    """Builds an 'adb' commandline with the given args."""
    result = [self.adb]
    if self.device_id:
      result.append('-s')
      result.append(self.device_id)
    result += list(args)
    return result


class AdbAmMonitorWatcher(object):
  """Watches an "adb shell am monitor" process to detect crashes."""

  def __init__(self, launcher, done_queue):
    self.launcher = launcher
    self.process = launcher._PopenAdb(
        'shell', 'am', 'monitor', stdout=subprocess.PIPE)
    if abstract_launcher.ARG_DRYRUN in launcher.launcher_args:
      self.thread = None
      return
    self.thread = threading.Thread(target=self._Run)
    self.thread.start()
    self.done_queue = done_queue

  def Shutdown(self):
    self.process.kill()
    if self.thread:
      self.thread.join()

  def _Run(self):
    while True:
      line = CleanLine(self.process.stdout.readline().decode())
      if not line:
        return
      # Show the crash lines reported by "am monitor".
      sys.stderr.write(line)
      if re.search(_RE_ADB_AM_MONITOR_ERROR, line):
        self.done_queue.put(_QUEUE_CODE_CRASHED)
        # This log line will wake up the main thread
        self.launcher.CallAdb('shell', 'log', '-t', 'starboard',
                              'am monitor detected crash')


class Launcher(abstract_launcher.AbstractLauncher):
  """Run an application on Android."""

  def __init__(self, platform, target_name, config, device_id, **kwargs):

    super().__init__(platform, target_name, config, device_id, **kwargs)

    if abstract_launcher.ARG_SYSTOOLS in self.launcher_args:
      # Use default adb binary from path.
      self.adb = 'adb'
    else:
      self.adb = os.path.join(SDK_PATH, 'platform-tools', 'adb')

    self.adb_builder = AdbCommandBuilder(self.adb)

    if not self.device_id:
      self.device_id = self._IdentifyDevice()
    else:
      self._ConnectIfNecessary()

    self.adb_builder.device_id = self.device_id

    # Verify connection and dump target build fingerprint.
    self._CheckCallAdb('shell', 'getprop', 'ro.build.fingerprint')

    out_directory = os.path.split(self.GetTargetPath())[0]
    self.apk_path = os.path.join(out_directory, f'{target_name}.apk')
    if not os.path.exists(self.apk_path):
      raise Exception(f"Can't find APK {self.apk_path}")

    # This flag is set when the main Run() loop exits.  If Kill() is called
    # after this flag is set, it will not do anything.
    self.killed = threading.Event()

    # Keep track of the port used by ADB forward in order to remove it later
    # on.
    self.local_port = None

  def _IsValidIPv4Address(self, address):
    """Returns True if address is a valid IPv4 address, False otherwise."""
    try:
      # inet_aton throws an exception if the address is not a valid IPv4
      # address. However addresses such as '127.1' might still be considered
      # valid, hence the check for 3 '.' in the address.
      # pylint: disable=g-socket-inet-aton
      if socket.inet_aton(address) and address.count('.') == 3:
        return True
    except Exception:  # pylint: disable=broad-except
      pass
    return False

  def _GetAdbDevices(self):
    """Returns a list of names of connected devices, or empty list if none."""

    # Does not use the ADBCommandBuilder class because this command should be
    # run without targeting a specific device.
    p = self._PopenAdb('devices', stdout=subprocess.PIPE)
    result = p.stdout.readlines()[1:-1]
    p.wait()

    names = []
    for device in result:
      name_info = device.decode().split('\t')
      # Some devices may not have authorization for USB debugging.
      try:
        if 'unauthorized' not in name_info[1]:
          names.append(name_info[0])
      # Sometimes happens when device is found, even though none are connected.
      except IndexError:
        continue
    return names

  def _IdentifyDevice(self):
    """Picks a device to be used to run the executable.

    In the event that no device_id is provided, but multiple
    devices are connected, this method chooses the first device
    listed.

    Returns:
      The name of an attached device, or None if no devices are present.
    """
    device_name = None

    devices = self._GetAdbDevices()
    if devices:
      device_name = devices[0]

    return device_name

  def _ConnectIfNecessary(self):
    """Run ADB connect if needed for devices connected over IP."""
    if not self._IsValidIPv4Address(self.device_id):
      return
    for device in self._GetAdbDevices():
      # Devices returned by _GetAdbDevices might include port number, so cannot
      # simply check if self.device_id is in the returned list.
      if self.device_id in device:
        return

    # Device isn't connected. Run ADB connect.
    # Does not use the ADBCommandBuilder class because this command should be
    # run without targeting a specific device.
    p = self._PopenAdb(
        'connect',
        f'{self.device_id}:5555',
        stderr=subprocess.STDOUT,
        stdout=subprocess.PIPE,
    )
    result = p.stdout.readlines()[0]
    p.wait()

    if 'connected to' not in result:
      sys.stderr.write(f'Failed to connect to {self.device_id}\n')
      sys.stderr.write(f'connect command exited with code {p.returncode} '
                       f'and returned: {result}')

  def _Call(self, *args):
    sys.stderr.write(f"{' '.join(args)}\n")
    if abstract_launcher.ARG_DRYRUN not in self.launcher_args:
      subprocess.call(args, close_fds=True)

  def CallAdb(self, *in_args):
    args = self.adb_builder.Build(*in_args)
    self._Call(*args)

  def _CheckCall(self, *args):
    sys.stderr.write(f"{' '.join(args)}\n")
    if abstract_launcher.ARG_DRYRUN not in self.launcher_args:
      subprocess.check_call(args, close_fds=True)

  def _CheckCallAdb(self, *in_args):
    args = self.adb_builder.Build(*in_args)
    self._CheckCall(*args)

  def _PopenAdb(self, *args, **kwargs):
    build_args = self.adb_builder.Build(*args)
    sys.stderr.write(f"{' '.join(build_args)}\n")
    if abstract_launcher.ARG_DRYRUN in self.launcher_args:
      return subprocess.Popen(['echo', 'dry-run'])
    return subprocess.Popen(build_args, close_fds=True, **kwargs)

  def Run(self):
    # The return code for binaries run on Android is read from a log line that
    # it emitted in android_main.cc.  This return_code variable will be assigned
    # the value read when we see that line, or left at 1 in the event of a crash
    # or early exit.
    return_code = 1

    # Setup for running executable
    self._CheckCallAdb('wait-for-device')
    self._Shutdown()
    # TODO: Need to wait until cobalt fully shutdown. Otherwise, it may get
    # dirty logs from previous test, and logs like "***Application Stopped***"
    # will cause unexpected errors.
    # Simply wait 5s as a temporary solution.
    time.sleep(5)
    # Clear logcat
    self._CheckCallAdb('logcat', '-c')

    # Install the APK, unless "noinstall" was specified.
    if abstract_launcher.ARG_NOINSTALL not in self.launcher_args:
      install_timer = StepTimer('install')
      self._CheckCallAdb('install', '-r', self.apk_path)
      install_timer.Stop()

    # Send the wakeup key to ensure daydream isn't running, otherwise Activity
    # Manager may get in a loop running the test over and over again.
    self._CheckCallAdb('shell', 'input', 'keyevent', 'KEYCODE_WAKEUP')

    # Grant runtime permissions to avoid prompts during testing.
    if abstract_launcher.ARG_NOINSTALL not in self.launcher_args:
      for permission in _RUNTIME_PERMISSIONS:
        self._CheckCallAdb('shell', 'pm', 'grant', _APP_PACKAGE_NAME,
                           permission)

    done_queue = queue.Queue()
    am_monitor = AdbAmMonitorWatcher(self, done_queue)

    # Increases the size of the logcat buffer.  Without this, the log buffer
    # will not flush quickly enough and output will be cut off.
    self._CheckCallAdb('logcat', '-G', '2M')

    #  Ctrl + C will kill this process
    logcat_process = self._PopenAdb(
        'logcat',
        '-v',
        'raw',
        '-s',
        '*:F',
        '*:E',
        'DEBUG:*',
        'System.err:*',
        'starboard:*',
        'starboard_media:*',
        stdout=subprocess.PIPE,
        stderr=subprocess.STDOUT)

    # Actually running executable
    run_timer = StepTimer('running executable')
    app_crashed = False
    try:
      args = ['shell', 'am', 'start']
      command_line_params = [
          '--android_log_sleep_time=1000',
          '--disable_sign_in',
      ]
      for param in self.target_command_line_params:
        if param.startswith('--link='):
          # Android deeplinks go in the Intent data
          link = param.split('=')[1]
          args += ['-d', f"'{link}'"]
        else:
          command_line_params.append(param)
      args += ['--esa', 'args', f"'{','.join(command_line_params)}'"]
      args += [_APP_START_INTENT]

      self._CheckCallAdb(*args)

      run_loop = abstract_launcher.ARG_DRYRUN not in self.launcher_args

      while run_loop:
        if not done_queue.empty():
          done_queue_code = done_queue.get_nowait()
          if done_queue_code == _QUEUE_CODE_CRASHED:
            app_crashed = True
            threading.Timer(_CRASH_LOG_SECONDS, logcat_process.kill).start()

        # Note we cannot use "for line in logcat_process.stdout" because
        # that uses a large buffer which will cause us to deadlock.
        line = CleanLine(logcat_process.stdout.readline().decode())

        # Some crashes are not caught by the am_monitor thread, but they do
        # produce the following string in logcat before they exit.
        if 'beginning of crash' in line:
          app_crashed = True
          threading.Timer(_CRASH_LOG_SECONDS, logcat_process.kill).start()

        if not line:  # Logcat exited, or was killed
          break
        else:
          self._WriteLine(line)
          # Don't break until we see the below text in logcat, which should be
          # written when the Starboard application event loop finishes.
          if '***Application Stopped***' in line:
            try:
              return_code = int(line.split(' ')[-1])
            except ValueError:  # Error message was printed to stdout
              pass
            logcat_process.kill()
            break

    finally:
      if app_crashed:
        self._WriteLine('***Application Crashed***\n')
        # Set return code to mimic segfault code on Linux
        return_code = 11
      else:
        self._Shutdown()
      if self.local_port is not None:
        self.CallAdb('forward', '--remove', f'tcp:{self.local_port}')
      am_monitor.Shutdown()
      self.killed.set()
      run_timer.Stop()
      if logcat_process.poll() is None:
        # This could happen when using SIGINT to kill the launcher
        # (e.g. when using starboard/tools/example/app_launcher_client.py).
        sys.stderr.write('Logcat process is still running. Killing it now.\n')
        logcat_process.kill()

    return return_code

  def _Shutdown(self):
    self.CallAdb('shell', 'am', 'force-stop', _APP_PACKAGE_NAME)

  def SupportsDeepLink(self):
    return True

  def SendDeepLink(self, link):
    shell_cmd = f'am start -d "{link}" {_APP_START_INTENT}'
    args = ['shell', shell_cmd]
    self._CheckCallAdb(*args)
    return True

  def SupportsSystemSuspendResume(self):
    return True

  def SendSystemResume(self):
    self.CallAdb('shell', 'am', 'start', _APP_PACKAGE_NAME)
    return True

  def SendSystemSuspend(self):
    self.CallAdb('shell', 'input', 'keyevent', 'KEYCODE_HOME')
    return True

  def Kill(self):
    if not self.killed.is_set():
      sys.stderr.write('***Killing Launcher***\n')
      self._CheckCallAdb('shell', 'log', '-t', 'starboard',
                         '***Application Stopped*** 1')
      self._Shutdown()
    else:
      sys.stderr.write('Cannot kill launcher: already dead.\n')

  def _WriteLine(self, line):
    """Write log output to stdout."""
    self.output_file.write(line)
    self.output_file.flush()

  def GetHostAndPortGivenPort(self, port):
    forward_p = self._PopenAdb(
        'forward', 'tcp:0', f'tcp:{port}', stdout=subprocess.PIPE)
    forward_p.wait()

    self.local_port = CleanLine(
        forward_p.stdout.readline().decode()).rstrip('\n')
    sys.stderr.write(f'ADB forward local port {self.local_port} '
                     '=> device port {port}\n')
    # pylint: disable=g-socket-gethostbyname
    return socket.gethostbyname('localhost'), self.local_port

  def GetDeviceIp(self):
    """Gets the device IP. TODO: Implement."""
    return None

  def GetDeviceOutputPath(self):
    """Writable path where test targets can output files"""
    return f'/data/data/{_APP_PACKAGE_NAME}/cache/'
