# 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_adpater_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_hid_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(host, 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)
