# Copyright 2016 Google Inc.
#
# 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.
"""JSON RPC interface to Mobly Snippet Lib."""

from __future__ import print_function

import re
import time

from mobly import utils
from mobly.controllers.android_device_lib import adb
from mobly.controllers.android_device_lib import errors
from mobly.controllers.android_device_lib import jsonrpc_client_base

_INSTRUMENTATION_RUNNER_PACKAGE = (
    'com.google.android.mobly.snippet.SnippetRunner')

# Major version of the launch and communication protocol being used by this
# client.
# Incrementing this means that compatibility with clients using the older
# version is broken. Avoid breaking compatibility unless there is no other
# choice.
_PROTOCOL_MAJOR_VERSION = 1

# Minor version of the launch and communication protocol.
# Increment this when new features are added to the launch and communication
# protocol that are backwards compatible with the old protocol and don't break
# existing clients.
_PROTOCOL_MINOR_VERSION = 0

_LAUNCH_CMD = (
    '{shell_cmd} am instrument {user} -w -e action start {snippet_package}/' +
    _INSTRUMENTATION_RUNNER_PACKAGE)

_STOP_CMD = ('am instrument {user} -w -e action stop {snippet_package}/' +
             _INSTRUMENTATION_RUNNER_PACKAGE)

# Test that uses UiAutomation requires the shell session to be maintained while
# test is in progress. However, this requirement does not hold for the test that
# deals with device USB disconnection (Once device disconnects, the shell
# session that started the instrument ends, and UiAutomation fails with error:
# "UiAutomation not connected"). To keep the shell session and redirect
# stdin/stdout/stderr, use "setsid" or "nohup" while launching the
# instrumentation test. Because these commands may not be available in every
# android system, try to use them only if exists.
_SETSID_COMMAND = 'setsid'

_NOHUP_COMMAND = 'nohup'


class AppStartPreCheckError(jsonrpc_client_base.Error):
    """Raised when pre checks for the snippet failed."""


class ProtocolVersionError(jsonrpc_client_base.AppStartError):
    """Raised when the protocol reported by the snippet is unknown."""


class SnippetClient(jsonrpc_client_base.JsonRpcClientBase):
    """A client for interacting with snippet APKs using Mobly Snippet Lib.

    See superclass documentation for a list of public attributes.

    For a description of the launch protocols, see the documentation in
    mobly-snippet-lib, SnippetRunner.java.
    """

    def __init__(self, package, ad):
        """Initializes a SnippetClient.

        Args:
            package: (str) The package name of the apk where the snippets are
                defined.
            ad: (AndroidDevice) the device object associated with this client.
        """
        super(SnippetClient, self).__init__(app_name=package, ad=ad)
        self.package = package
        self._ad = ad
        self._adb = ad.adb
        self._proc = None

    @property
    def is_alive(self):
        """Is the client alive.

        The client is considered alive if there is a connection object held for
        it. This is an approximation due to the following scenario:

        In the USB disconnect case, the host subprocess that kicked off the
        snippet  apk would die, but the snippet apk itself would continue
        running on the device.

        The best approximation we can make is, the connection object has not
        been explicitly torn down, so the client should be considered alive.

        Returns:
            True if the client is considered alive, False otherwise.
        """
        return self._conn is not None

    def _get_user_command_string(self):
        """Gets the appropriate command argument for specifying user IDs.

        By default, `SnippetClient` operates within the current user.

        We don't add the `--user {ID}` arg when Android's SDK is below 24,
        where multi-user support is not well implemented.

        Returns:
            String, the command param section to be formatted into the adb
            commands.
        """
        sdk_int = int(self._ad.build_info['build_version_sdk'])
        if sdk_int < 24:
            return ''
        return '--user %s' % self._adb.current_user_id

    def start_app_and_connect(self):
        """Starts snippet apk on the device and connects to it.

        This wraps the main logic with safe handling

        Raises:
            AppStartPreCheckError, when pre-launch checks fail.
        """
        try:
            self._start_app_and_connect()
        except AppStartPreCheckError:
            # Precheck errors don't need cleanup, directly raise.
            raise
        except Exception as e:
            # Log the stacktrace of `e` as re-raising doesn't preserve trace.
            self._ad.log.exception('Failed to start app and connect.')
            # If errors happen, make sure we clean up before raising.
            try:
                self.stop_app()
            except:
                self._ad.log.exception(
                    'Failed to stop app after failure to start and connect.')
            # Explicitly raise the original error from starting app.
            raise e

    def _start_app_and_connect(self):
        """Starts snippet apk on the device and connects to it.

        After prechecks, this launches the snippet apk with an adb cmd in a
        standing subprocess, checks the cmd response from the apk for protocol
        version, then sets up the socket connection over adb port-forwarding.

        Args:
            ProtocolVersionError, if protocol info or port info cannot be
                retrieved from the snippet apk.
        """
        self._check_app_installed()
        self.disable_hidden_api_blacklist()

        persists_shell_cmd = self._get_persist_command()
        # Use info here so people can follow along with the snippet startup
        # process. Starting snippets can be slow, especially if there are
        # multiple, and this avoids the perception that the framework is hanging
        # for a long time doing nothing.
        self.log.info('Launching snippet apk %s with protocol %d.%d',
                      self.package, _PROTOCOL_MAJOR_VERSION,
                      _PROTOCOL_MINOR_VERSION)
        cmd = _LAUNCH_CMD.format(shell_cmd=persists_shell_cmd,
                                 user=self._get_user_command_string(),
                                 snippet_package=self.package)
        start_time = time.time()
        self._proc = self._do_start_app(cmd)

        # Check protocol version and get the device port
        line = self._read_protocol_line()
        match = re.match('^SNIPPET START, PROTOCOL ([0-9]+) ([0-9]+)$', line)
        if not match or match.group(1) != '1':
            raise ProtocolVersionError(self._ad, line)

        line = self._read_protocol_line()
        match = re.match('^SNIPPET SERVING, PORT ([0-9]+)$', line)
        if not match:
            raise ProtocolVersionError(self._ad, line)
        self.device_port = int(match.group(1))

        # Forward the device port to a new host port, and connect to that port
        self.host_port = utils.get_available_host_port()
        self._adb.forward(
            ['tcp:%d' % self.host_port,
             'tcp:%d' % self.device_port])
        self.connect()

        # Yaaay! We're done!
        self.log.debug('Snippet %s started after %.1fs on host port %s',
                       self.package,
                       time.time() - start_time, self.host_port)

    def restore_app_connection(self, port=None):
        """Restores the app after device got reconnected.

        Instead of creating new instance of the client:
          - Uses the given port (or find a new available host_port if none is
            given).
          - Tries to connect to remote server with selected port.

        Args:
          port: If given, this is the host port from which to connect to remote
              device port. If not provided, find a new available port as host
              port.

        Raises:
            AppRestoreConnectionError: When the app was not able to be started.
        """
        self.host_port = port or utils.get_available_host_port()
        self._adb.forward(
            ['tcp:%d' % self.host_port,
             'tcp:%d' % self.device_port])
        try:
            self.connect()
        except:
            # Log the original error and raise AppRestoreConnectionError.
            self.log.exception('Failed to re-connect to app.')
            raise jsonrpc_client_base.AppRestoreConnectionError(
                self._ad,
                ('Failed to restore app connection for %s at host port %s, '
                 'device port %s') %
                (self.package, self.host_port, self.device_port))

        # Because the previous connection was lost, update self._proc
        self._proc = None
        self._restore_event_client()

    def stop_app(self):
        # Kill the pending 'adb shell am instrument -w' process if there is one.
        # Although killing the snippet apk would abort this process anyway, we
        # want to call stop_standing_subprocess() to perform a health check,
        # print the failure stack trace if there was any, and reap it from the
        # process table.
        self.log.debug('Stopping snippet apk %s', self.package)
        try:
            # Close the socket connection.
            self.disconnect()
            if self._proc:
                utils.stop_standing_subprocess(self._proc)
            self._proc = None
            out = self._adb.shell(
                _STOP_CMD.format(
                    snippet_package=self.package,
                    user=self._get_user_command_string())).decode('utf-8')
            if 'OK (0 tests)' not in out:
                raise errors.DeviceError(
                    self._ad,
                    'Failed to stop existing apk. Unexpected output: %s' % out)
        finally:
            # Always clean up the adb port
            self.clear_host_port()

    def _start_event_client(self):
        """Overrides superclass."""
        event_client = SnippetClient(package=self.package, ad=self._ad)
        event_client.host_port = self.host_port
        event_client.device_port = self.device_port
        event_client.connect(self.uid,
                             jsonrpc_client_base.JsonRpcCommand.CONTINUE)
        return event_client

    def _restore_event_client(self):
        """Restores previously created event client."""
        if not self._event_client:
            self._event_client = self._start_event_client()
            return
        self._event_client.host_port = self.host_port
        self._event_client.device_port = self.device_port
        self._event_client.connect()

    def _check_app_installed(self):
        # Check that the Mobly Snippet app is installed for the current user.
        user_id = self._adb.current_user_id
        out = self._adb.shell('pm list package --user %s' % user_id)
        if not utils.grep('^package:%s$' % self.package, out):
            raise AppStartPreCheckError(
                self._ad,
                '%s is not installed for user %s.' % (self.package, user_id))
        # Check that the app is instrumented.
        out = self._adb.shell('pm list instrumentation')
        matched_out = utils.grep(
            '^instrumentation:%s/%s' %
            (self.package, _INSTRUMENTATION_RUNNER_PACKAGE), out)
        if not matched_out:
            raise AppStartPreCheckError(
                self._ad,
                '%s is installed, but it is not instrumented.' % self.package)
        match = re.search(r'^instrumentation:(.*)\/(.*) \(target=(.*)\)$',
                          matched_out[0])
        target_name = match.group(3)
        # Check that the instrumentation target is installed if it's not the
        # same as the snippet package.
        if target_name != self.package:
            out = self._adb.shell('pm list package --user %s' % user_id)
            if not utils.grep('^package:%s$' % target_name, out):
                raise AppStartPreCheckError(
                    self._ad,
                    'Instrumentation target %s is not installed for user %s.' %
                    (target_name, user_id))

    def _do_start_app(self, launch_cmd):
        adb_cmd = [adb.ADB]
        if self._adb.serial:
            adb_cmd += ['-s', self._adb.serial]
        adb_cmd += ['shell', launch_cmd]
        return utils.start_standing_subprocess(adb_cmd, shell=False)

    def _read_protocol_line(self):
        """Reads the next line of instrumentation output relevant to snippets.

        This method will skip over lines that don't start with 'SNIPPET' or
        'INSTRUMENTATION_RESULT'.

        Returns:
            (str) Next line of snippet-related instrumentation output, stripped.

        Raises:
            jsonrpc_client_base.AppStartError: If EOF is reached without any
                protocol lines being read.
        """
        while True:
            line = self._proc.stdout.readline().decode('utf-8')
            if not line:
                raise jsonrpc_client_base.AppStartError(
                    self._ad, 'Unexpected EOF waiting for app to start')
            # readline() uses an empty string to mark EOF, and a single newline
            # to mark regular empty lines in the output. Don't move the strip()
            # call above the truthiness check, or this method will start
            # considering any blank output line to be EOF.
            line = line.strip()
            if (line.startswith('INSTRUMENTATION_RESULT:')
                    or line.startswith('SNIPPET ')):
                self.log.debug(
                    'Accepted line from instrumentation output: "%s"', line)
                return line
            self.log.debug('Discarded line from instrumentation output: "%s"',
                           line)

    def _get_persist_command(self):
        """Check availability and return path of command if available."""
        for command in [_SETSID_COMMAND, _NOHUP_COMMAND]:
            try:
                if command in self._adb.shell(['which',
                                               command]).decode('utf-8'):
                    return command
            except adb.AdbError:
                continue
        self.log.warning(
            'No %s and %s commands available to launch instrument '
            'persistently, tests that depend on UiAutomator and '
            'at the same time performs USB disconnection may fail',
            _SETSID_COMMAND, _NOHUP_COMMAND)
        return ''

    def help(self, print_output=True):
        """Calls the help RPC, which returns the list of RPC calls available.

        This RPC should normally be used in an interactive console environment
        where the output should be printed instead of returned. Otherwise,
        newlines will be escaped, which will make the output difficult to read.

        Args:
            print_output: A bool for whether the output should be printed.

        Returns:
            A str containing the help output otherwise None if print_output
                wasn't set.
        """
        help_text = self._rpc('help')
        if print_output:
            print(help_text)
        else:
            return help_text
