# Copyright 2015 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.

"""This module provides the utilities for bluetooth audio using chameleon."""

import logging
import time

from autotest_lib.client.bin import utils


_PIN = '0000'
_SEARCH_TIMEOUT = 30.0
_PAIRING_TIMEOUT = 5.0
_SLEEP_AFTER_DISCONNECT = 20.0
# When device is busy, a trial may take more than 15 seconds.
# Set the timeout to 90 seconds so device can take more trials to reconnect.
_CONNECT_TIMEOUT = 90.0

class ChameleonBluetoothAudioError(Exception):
    """Error in this module."""
    pass


def connect_bluetooth_module_full_flow(bt_adapter, target_mac_address,
                             timeout=_SEARCH_TIMEOUT):
    """Controls Cros device to connect to bluetooth module on audio board.

    @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
                       on Cros device.
    @param target_mac_address: The MAC address of bluetooth module to be
                               connected.
    @param timeout: Timeout in seconds to search for bluetooth module.

    @raises: ChameleonBluetoothAudioError if Cros device fails to connect to
             bluetooth module on audio board.

    """
    # Resets bluetooth adapter on Cros device.
    if not bt_adapter.reset_on():
        raise ChameleonBluetoothAudioError(
                'Failed to reset bluetooth adapter on Cros host.'
                ' You should check if controller is available on Cros host'
                ' using bluetoothctl.')

    # Starts discovery mode of bluetooth adapter.
    if not bt_adapter.start_discovery():
        raise ChameleonBluetoothAudioError(
                'Failed to start discovery on bluetooth adapter on Cros host')

    def _find_device():
        """Controls bluetooth adapter to search for bluetooth module.

        @returns: True if there is a bluetooth device with MAC address
                  matches target_mac_address. False otherwise.

        """
        return bt_adapter.has_device(target_mac_address)

    # Searches for bluetooth module with given MAC address.
    found_device = utils.wait_for_value(_find_device, True, timeout_sec=timeout)
    if not bt_adapter.stop_discovery():
        raise ChameleonBluetoothAudioError(
            'Failed to stop discovery on bluetooth adapter on Cros host')

    if not found_device:
        raise ChameleonBluetoothAudioError(
                'Can not find bluetooth module with MAC address %s' %
                target_mac_address)

    pair_legacy_bluetooth_module(bt_adapter, target_mac_address)

    # Disconnects from bluetooth module to clean up the state.
    if not bt_adapter.disconnect_device(target_mac_address):
        raise ChameleonBluetoothAudioError(
                'Failed to let Cros device disconnect from bluetooth module %s' %
                target_mac_address)
    time.sleep(_SLEEP_AFTER_DISCONNECT)

    # Connects to bluetooth module.
    connect_bluetooth_module(bt_adapter, target_mac_address)

    logging.info('Bluetooth module at %s is connected', target_mac_address)


def connect_bluetooth_module(bt_adapter, target_mac_address,
                             timeout=_CONNECT_TIMEOUT):
    """Controls Cros device to connect to bluetooth module on audio board.

    @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
                       on Cros device.
    @param target_mac_address: The MAC address of bluetooth module to be
                               connected.
    @param timeout: Timeout in seconds to connect bluetooth module.

    @raises: ChameleonBluetoothAudioError if Cros device fails to connect to
             bluetooth module on audio board.

    """
    def _connect_device():
        logging.info('Try to connect to device')
        success = bt_adapter.connect_device(target_mac_address)
        if not success:
            logging.debug('Can not connect device, retry in 1 second.')
            time.sleep(1)
            return False
        logging.debug('Connection established.')
        return True

    # Connects bluetooth module with given MAC address.
    connected = utils.wait_for_value(_connect_device, True, timeout_sec=timeout)
    if not connected:
        raise ChameleonBluetoothAudioError(
                'Failed to let Cros device connect to bluetooth module %s' %
                target_mac_address)


def pair_legacy_bluetooth_module(bt_adapter, target_mac_address, pin=_PIN,
                                 pairing_timeout=_PAIRING_TIMEOUT, retries=3):
    """Pairs Cros device bluetooth adapter with legacy bluetooth module.

    @param bt_adapter: A BluetoothDevice object to control bluetooth adapter
                       on Cros device.
    @param target_mac_address: The MAC address of bluetooth module to be
                               paired.
    @param pin: The pin for legacy pairing.
    @param timeout: Timeout in seconds to pair bluetooth module in a trial.
    @param retries: Number of retries if pairing fails.

    @raises: ChameleonBluetoothAudioError if Cros device fails to pair
             bluetooth module on audio board after all the retries.

    """
    # Pairs the bluetooth adapter with bluetooth module.
    for trial in xrange(retries):
        if bt_adapter.pair_legacy_device(
            target_mac_address, pin, False, pairing_timeout):
                logging.debug('Pairing to %s succeeded', target_mac_address)
                return
        elif trial == retries - 1:
            raise ChameleonBluetoothAudioError(
                    'Failed to pair Cros device and bluetooth module %s' %
                    target_mac_address)

        logging.debug('Retry for pairing...')


class BluetoothRefController(object):
    """
    An abstraction of bluetooth module on Fizz.
    Analogous to BluetoothController defined in audio_board.py for
    Chameleon hardware.

    """
    def __init__(self, chameleon_connection):
        """Constructs a BluetoothController.

        @param chameleon_connection: A ChameleonConnection object.

        """
        self._chameleond_proxy = chameleon_connection.chameleond_proxy


    def reset(self):
        """Resets the bluetooth Ref."""
        self._chameleond_proxy.ResetBluetoothRef()
        logging.info('Resets bluetooth Ref.')


    def enable(self):
        """Disables the bluetooth Ref."""
        self._chameleond_proxy.EnableBluetoothRef()
        logging.info('Disables bluetooth Ref.')

    def disable(self):
        """Disables the bluetooth Ref."""
        self._chameleond_proxy.DisableBluetoothRef()
        logging.info('Disables bluetooth Ref.')


    def is_enabled(self):
        """Checks if the bluetooth Ref is enabled.

        @returns: True if bluetooth module is enabled. False otherwise.

        """
        """
        TODO (npoojary):
        return self._chameleond_proxy.IsBluetoothRefEnabled()
        """
        return True
