# Lint as: python2, python3
# 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."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import logging
import time

from autotest_lib.client.bin import utils
from six.moves import range


_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.
    status, _ = bt_adapter.start_discovery()
    if not status:
        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)
    status, _ =  bt_adapter.stop_discovery()
    if not status:
        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 range(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


    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
