# Copyright 2016 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

"""Server side bluetooth tests on adapter pairing and connecting to a bluetooth
HID device.
"""

import logging
import time

from autotest_lib.client.common_lib import error
from autotest_lib.server.cros.bluetooth.bluetooth_adapter_tests import (
        BluetoothAdapterTests)
from autotest_lib.server.cros.multimedia import remote_facade_factory


class bluetooth_AdapterPairing(BluetoothAdapterTests):
    """Server side bluetooth adapter pairing and connecting to bluetooth device

    This test tries to verify that the adapter of the DUT could
    pair and connect to a bluetooth HID device correctly.

    In particular, the following subtests are performed. Look at the
    docstrings of the subtests for more details.
    -

    Refer to BluetoothAdapterTests for all subtests performed in this test.

    """

    # TODO(josephsih): Reduce the sleep intervals to speed up the tests.
    TEST_SLEEP_SECS = 5

    def run_once(self, host, device_type, num_iterations=1, min_pass_count=1,
                 pairing_twice=False):
        """Running Bluetooth adapter tests about pairing to a device.

        @param host: the DUT, usually a chromebook
        @param device_type : the bluetooth HID device type, e.g., 'MOUSE'
        @param num_iterations: the number of rounds to execute the test
        @param min_pass_count: the minimal pass count to pass this test
        @param pairing_twice: True if the host tries to pair the device
                again after the paired device is removed.

        """
        self.host = host
        factory = remote_facade_factory.RemoteFacadeFactory(host)
        self.bluetooth_facade = factory.create_bluetooth_hid_facade()

        pass_count = 0
        self.total_fails = {}
        for iteration in xrange(1, num_iterations + 1):
            self.fails = []

            # Get the device object and query some important properties.
            device = self.get_device(device_type)

            # Reset the adapter to forget previously paired devices if any.
            self.test_reset_on_adapter()

            # The adapter must be set to the pairable state.
            self.test_pairable()

            # Test if the adapter could discover the target device.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_discover_device(device.address)

            # Test if the discovery could be stopped.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_stop_discovery()

            # Test if the discovered device class of service is correct.
            self.test_device_class_of_service(device.address,
                                              device.class_of_service)

            # Test if the discovered device class of device is correct.
            self.test_device_class_of_device(device.address,
                                             device.class_of_device)

            # Verify that the adapter could pair with the device.
            # Also set the device trusted when pairing is done.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_pairing(device.address, device.pin, trusted=True)

            # Verify that the adapter could connect to the device.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_connection_by_adapter(device.address)

            # Test if the discovered device name is correct.
            # Sometimes, it takes quite a long time after discovering
            # the device (more than 60 seconds) to resolve the device name.
            # Hence, it is safer to test the device name after pairing and
            # connection is done.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_device_name(device.address, device.name)

            # Verify that the adapter could disconnect the device.
            self.test_disconnection_by_adapter(device.address)

            # Verify that the device could initiate the connection.
            time.sleep(self.TEST_SLEEP_SECS)
            self.test_connection_by_device(device)

            # Verify that the device could initiate the disconnection.
            self.test_disconnection_by_device(device)

            # Verify that the adapter could remove the paired device.
            self.test_remove_pairing(device.address)

            # Check if the device could be re-paired after being forgotten.
            if pairing_twice:
                # Test if the adapter could discover the target device again.
                time.sleep(self.TEST_SLEEP_SECS)
                self.test_discover_device(device.address)

                # Verify that the adapter could pair with the device again.
                # Also set the device trusted when pairing is done.
                time.sleep(self.TEST_SLEEP_SECS)
                self.test_pairing(device.address, device.pin, trusted=True)

                # Verify that the adapter could remove the paired device again.
                time.sleep(self.TEST_SLEEP_SECS)
                self.test_remove_pairing(device.address)

            if bool(self.fails):
                self.total_fails['Round %d' % iteration] = self.fails
            else:
                pass_count += 1

            fail_count = iteration - pass_count
            logging.info('===  (pass = %d, fail = %d) / total %d  ===\n',
                         pass_count, fail_count, num_iterations)

        if pass_count < min_pass_count:
            raise error.TestFail(self.total_fails)
