# 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 android scripting engine."""

import time

from mobly import utils
from mobly.controllers.android_device_lib import event_dispatcher
from mobly.controllers.android_device_lib import jsonrpc_client_base

_APP_NAME = 'SL4A'
_DEVICE_SIDE_PORT = 8080
_LAUNCH_CMD = (
    'am start -a com.googlecode.android_scripting.action.LAUNCH_SERVER '
    '--ei com.googlecode.android_scripting.extra.USE_SERVICE_PORT %s '
    'com.googlecode.android_scripting/.activity.ScriptingLayerServiceLauncher')
# Maximum time to wait for the app to start on the device (10 minutes).
# TODO: This timeout is set high in order to allow for retries in
# start_app_and_connect. Decrease it when the call to connect() has the option
# for a quicker timeout than the default _cmd() timeout.
# TODO: Evaluate whether the high timeout still makes sense for sl4a. It was
# designed for user snippets which could be very slow to start depending on the
# size of the snippet and main apps. sl4a can probably use a much smaller value.
_APP_START_WAIT_TIME = 2 * 60


class Sl4aClient(jsonrpc_client_base.JsonRpcClientBase):
    """A client for interacting with SL4A using Mobly Snippet Lib.

    Extra public attributes:
    ed: Event dispatcher instance for this sl4a client.
    """

    def __init__(self, ad):
        """Initializes an Sl4aClient.

        Args:
            ad: AndroidDevice object.
        """
        super(Sl4aClient, self).__init__(app_name=_APP_NAME, ad=ad)
        self._ad = ad
        self.ed = None
        self._adb = ad.adb

    def start_app_and_connect(self):
        """Overrides superclass."""
        # Check that sl4a is installed
        out = self._adb.shell('pm list package')
        if not utils.grep('com.googlecode.android_scripting', out):
            raise jsonrpc_client_base.AppStartError(
                self._ad,
                '%s is not installed on %s' % (_APP_NAME, self._adb.serial))
        self.disable_hidden_api_blacklist()

        # sl4a has problems connecting after disconnection, so kill the apk and
        # try connecting again.
        try:
            self.stop_app()
        except Exception as e:
            self.log.warning(e)

        # Launch the app
        self.device_port = _DEVICE_SIDE_PORT
        self._adb.shell(_LAUNCH_CMD % self.device_port)

        # Try to start the connection (not restore the connectivity).
        # The function name restore_app_connection is used here is for the
        # purpose of reusing the same code as it does when restoring the
        # connection. And we do not want to come up with another function
        # name to complicate the API. Change the name if necessary.
        self.restore_app_connection()

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

        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._retry_connect()
        self.ed = self._start_event_client()

    def stop_app(self):
        """Overrides superclass."""
        try:
            if self._conn:
                # Be polite; let the dest know we're shutting down.
                try:
                    self.closeSl4aSession()
                except:
                    self.log.exception('Failed to gracefully shut down %s.',
                                       self.app_name)

                # Close the socket connection.
                self.disconnect()
                self.stop_event_dispatcher()

            # Terminate the app
            self._adb.shell('am force-stop com.googlecode.android_scripting')
        finally:
            # Always clean up the adb port
            self.clear_host_port()

    def stop_event_dispatcher(self):
        # Close Event Dispatcher
        if self.ed:
            try:
                self.ed.clean_up()
            except:
                self.log.exception('Failed to shutdown sl4a event dispatcher.')
            self.ed = None

    def _retry_connect(self):
        self._adb.forward(
            ['tcp:%d' % self.host_port,
             'tcp:%d' % self.device_port])
        start_time = time.time()
        expiration_time = start_time + _APP_START_WAIT_TIME
        started = False
        while time.time() < expiration_time:
            self.log.debug('Attempting to start %s.', self.app_name)
            try:
                self.connect()
                started = True
                break
            except:
                self.log.debug('%s is not yet running, retrying',
                               self.app_name,
                               exc_info=True)
            time.sleep(1)
        if not started:
            raise jsonrpc_client_base.AppRestoreConnectionError(
                self._ad, '%s failed to connect for %s at host port %s, '
                'device port %s' % (self.app_name, self._adb.serial,
                                    self.host_port, self.device_port))

    def _start_event_client(self):
        # Start an EventDispatcher for the current sl4a session
        event_client = Sl4aClient(self._ad)
        event_client.host_port = self.host_port
        event_client.device_port = self.device_port
        event_client.connect(uid=self.uid,
                             cmd=jsonrpc_client_base.JsonRpcCommand.CONTINUE)
        ed = event_dispatcher.EventDispatcher(event_client)
        ed.start()
        return ed
