# 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 {user} -w -e action start {snippet_package}/'
    + _INSTRUMENTATION_RUNNER_PACKAGE)

_STOP_CMD = ('am instrument -w -e action stop %s/' +
             _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 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._adb.current_user_id,
                                 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 % self.package).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
