#!/usr/bin/env python3
#
#   Copyright 2018 - The Android Open Source Project
#
#   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.
import socket
import threading

import errno

from acts import logger
from acts.controllers.adb_lib.error import AdbError
from acts.controllers.sl4a_lib import event_dispatcher
from acts.controllers.sl4a_lib import rpc_connection
from acts.controllers.sl4a_lib import rpc_client
from acts.controllers.sl4a_lib import sl4a_ports
from acts.controllers.sl4a_lib.rpc_client import Sl4aStartError

SOCKET_TIMEOUT = 60

# The SL4A Session UID when a UID has not been received yet.
UNKNOWN_UID = -1


class Sl4aSession(object):
    """An object that tracks the state of an SL4A Session.

    Attributes:
        _event_dispatcher: The EventDispatcher instance, if any, for this
            session.
        _terminate_lock: A lock that prevents race conditions for multiple
            threads calling terminate()
        _terminated: A bool that stores whether or not this session has been
            terminated. Terminated sessions cannot be restarted.
        adb: A reference to the AndroidDevice's AdbProxy.
        log: The logger for this Sl4aSession
        server_port: The SL4A server port this session is established on.
        uid: The uid that corresponds the the SL4A Server's session id. This
            value is only unique during the lifetime of the SL4A apk.
    """

    def __init__(self,
                 adb,
                 host_port,
                 device_port,
                 get_server_port_func,
                 on_error_callback,
                 max_connections=None):
        """Creates an SL4A Session.

        Args:
            adb: A reference to the adb proxy
            get_server_port_func: A lambda (int) that returns the corrected
                server port. The int passed in hints at which port to use, if
                possible.
            host_port: The port the host machine uses to connect to the SL4A
                server for its first connection.
            device_port: The SL4A server port to be used as a hint for which
                SL4A server to connect to.
        """
        self._event_dispatcher = None
        self._terminate_lock = threading.Lock()
        self._terminated = False
        self.adb = adb

        def _log_formatter(message):
            return '[SL4A Session|%s|%s] %s' % (self.adb.serial, self.uid,
                                                message)

        self.log = logger.create_logger(_log_formatter)

        self.server_port = device_port
        self.uid = UNKNOWN_UID
        self.obtain_server_port = get_server_port_func
        self._on_error_callback = on_error_callback

        connection_creator = self._rpc_connection_creator(host_port)
        self.rpc_client = rpc_client.RpcClient(
            self.uid,
            self.adb.serial,
            self.diagnose_failure,
            connection_creator,
            max_connections=max_connections)

    def _rpc_connection_creator(self, host_port):
        def create_client(uid):
            return self._create_rpc_connection(
                ports=sl4a_ports.Sl4aPorts(host_port, 0, self.server_port),
                uid=uid)

        return create_client

    @property
    def is_alive(self):
        return not self._terminated

    def _create_forwarded_port(self, server_port, hinted_port=0):
        """Creates a forwarded port to the specified server port.

        Args:
            server_port: (int) The port to forward to.
            hinted_port: (int) The port to use for forwarding, if available.
                         Otherwise, the chosen port will be random.
        Returns:
            The chosen forwarded port.

        Raises AdbError if the version of ADB is too old, or the command fails.
        """
        if self.adb.get_version_number() < 37 and hinted_port == 0:
            self.log.error(
                'The current version of ADB does not automatically provide a '
                'port to forward. Please upgrade ADB to version 1.0.37 or '
                'higher.')
            raise Sl4aStartError('Unable to forward a port to the device.')
        else:
            try:
                return self.adb.tcp_forward(hinted_port, server_port)
            except AdbError as e:
                if 'cannot bind listener' in e.stderr:
                    self.log.warning(
                        'Unable to use %s to forward to device port %s due to: '
                        '"%s". Attempting to choose a random port instead.' %
                        (hinted_port, server_port, e.stderr))
                    # Call this method again, but this time with no hinted port.
                    return self._create_forwarded_port(server_port)
                raise e

    def _create_rpc_connection(self, ports=None, uid=UNKNOWN_UID):
        """Creates an RPC Connection with the specified ports.

        Args:
            ports: A Sl4aPorts object or a tuple of (host/client_port,
                   forwarded_port, device/server_port). If any of these are
                   zero, the OS will determine their values during connection.

                   Note that these ports are only suggestions. If they are not
                   available, the a different port will be selected.
            uid: The UID of the SL4A Session. To create a new session, use
                 UNKNOWN_UID.
        Returns:
            An Sl4aClient.
        """
        if ports is None:
            ports = sl4a_ports.Sl4aPorts(0, 0, 0)
        # Open a new server if a server cannot be inferred.
        ports.server_port = self.obtain_server_port(ports.server_port)
        self.server_port = ports.server_port
        # Forward the device port to the host.
        ports.forwarded_port = self._create_forwarded_port(ports.server_port)
        client_socket, fd = self._create_client_side_connection(ports)
        client = rpc_connection.RpcConnection(
            self.adb, ports, client_socket, fd, uid=uid)
        client.open()
        if uid == UNKNOWN_UID:
            self.uid = client.uid
        return client

    def diagnose_failure(self, connection):
        """Diagnoses any problems related to the SL4A session."""
        self._on_error_callback(self, connection)

    def get_event_dispatcher(self):
        """Returns the EventDispatcher for this Sl4aSession."""
        if self._event_dispatcher is None:
            self._event_dispatcher = event_dispatcher.EventDispatcher(
                self.adb.serial, self.rpc_client)
        return self._event_dispatcher

    def _create_client_side_connection(self, ports):
        """Creates and connects the client socket to the forward device port.

        Args:
            ports: A Sl4aPorts object or a tuple of (host_port,
            forwarded_port, device_port).

        Returns:
            A tuple of (socket, socket_file_descriptor).
        """
        client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        client_socket.settimeout(SOCKET_TIMEOUT)
        client_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        if ports.client_port != 0:
            try:
                client_socket.bind((socket.gethostname(), ports.client_port))
            except OSError as e:
                # If the port is in use, log and ask for any open port.
                if e.errno == errno.EADDRINUSE:
                    self.log.warning(
                        'Port %s is already in use on the host. '
                        'Generating a random port.' % ports.client_port)
                    ports.client_port = 0
                    return self._create_client_side_connection(ports)
                raise

        # Verify and obtain the port opened by SL4A.
        try:
            # Connect to the port that has been forwarded to the device.
            client_socket.connect(('127.0.0.1', ports.forwarded_port))
        except socket.timeout:
            raise rpc_client.Sl4aConnectionError(
                'SL4A has not connected over the specified port within the '
                'timeout of %s seconds.' % SOCKET_TIMEOUT)
        except socket.error as e:
            # In extreme, unlikely cases, a socket error with
            # errno.EADDRNOTAVAIL can be raised when a desired host_port is
            # taken by a separate program between the bind and connect calls.
            # Note that if host_port is set to zero, there is no bind before
            # the connection is made, so this error will never be thrown.
            if e.errno == errno.EADDRNOTAVAIL:
                ports.client_port = 0
                return self._create_client_side_connection(ports)
            raise
        ports.client_port = client_socket.getsockname()[1]
        return client_socket, client_socket.makefile(mode='brw')

    def terminate(self):
        """Terminates the session.

        The return of process execution is blocked on completion of all events
        being processed by handlers in the Event Dispatcher.
        """
        with self._terminate_lock:
            if not self._terminated:
                self.log.debug('Terminating Session.')
                try:
                    self.rpc_client.closeSl4aSession()
                except Exception as e:
                    if "SL4A session has already been terminated" not in str(
                            e):
                        self.log.warning(e)
                # Must be set after closeSl4aSession so the rpc_client does not
                # think the session has closed.
                self._terminated = True
                if self._event_dispatcher:
                    try:
                        self._event_dispatcher.close()
                    except Exception as e:
                        self.log.warning(e)
                try:
                    self.rpc_client.terminate()
                except Exception as e:
                    self.log.warning(e)
