# Copyright 2014 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 link between audio widgets."""

import logging
import time

from autotest_lib.client.cros.chameleon import audio_level
from autotest_lib.client.cros.chameleon import chameleon_bluetooth_audio


class WidgetBinderError(Exception):
    """Error in WidgetBinder."""
    pass


class WidgetBinder(object):
    """
    This class abstracts the binding controls between two audio widgets.

     ________          __________________          ______
    |        |        |      link        |        |      |
    | source |------->| input     output |------->| sink |
    |________|        |__________________|        |______|

    Properties:
        _source: An AudioWidget object. The audio source. This should be
                 an output widget.
        _sink: An AudioWidget object. The audio sink. This should be an
                 input widget.
        _link: An WidgetLink object to link source and sink.
        _connected: True if this binder is connected.
        _level_controller: A LevelController to set scale and balance levels of
                           source and sink.
    """
    def __init__(self, source, link, sink):
        """Initializes a WidgetBinder.

        After initialization, the binder is not connected, but the link
        is occupied until it is released.
        After connection, the channel map of link will be set to the sink
        widget, and it will remains the same until the sink widget is connected
        to a different link. This is to make sure sink widget knows the channel
        map of recorded data even after link is disconnected or released.

        @param source: An AudioWidget object for audio source.
        @param link: A WidgetLink object to connect source and sink.
        @param sink: An AudioWidget object for audio sink.

        """
        self._source = source
        self._link = link
        self._sink = sink
        self._connected = False
        self._link.occupied = True
        self._level_controller = audio_level.LevelController(
                self._source, self._sink)


    def connect(self):
        """Connects source and sink to link."""
        if self._connected:
            return

        logging.info('Connecting %s to %s', self._source.audio_port,
                     self._sink.audio_port)
        self._link.connect(self._source, self._sink)
        self._connected = True
        # Sets channel map of link to the sink widget so
        # sink widget knows the channel map of recorded data.
        self._sink.channel_map = self._link.channel_map
        self._level_controller.set_scale()


    def disconnect(self):
        """Disconnects source and sink from link."""
        if not self._connected:
            return

        logging.info('Disconnecting %s from %s', self._source.audio_port,
                     self._sink.audio_port)
        self._link.disconnect(self._source, self._sink)
        self._connected = False
        self._level_controller.reset()


    def release(self):
        """Releases the link used by this binder.

        @raises: WidgetBinderError if this binder is still connected.

        """
        if self._connected:
            raise WidgetBinderError('Can not release while connected')
        self._link.occupied = False


    def get_link(self):
        """Returns the link controlled by this binder.

        The link provides more controls than binder so user can do
        more complicated tests.

        @returns: An object of subclass of WidgetLink.

        """
        return self._link


class WidgetLinkError(Exception):
    """Error in WidgetLink."""
    pass


class WidgetLink(object):
    """
    This class abstracts the link between two audio widgets.

    Properties:
        name: A string. The link name.
        occupied: True if this widget is occupied by a widget binder.
        channel_map: A list containing current channel map. Checks docstring
                     of channel_map method of AudioInputWidget for details.

    """
    def __init__(self):
        self.name = 'Unknown'
        self.occupied = False
        self.channel_map = None


    def _check_widget_id(self, port_id, widget):
        """Checks that the port id of a widget is expected.

        @param port_id: An id defined in chameleon_audio_ids.
        @param widget: An AudioWidget object.

        @raises: WidgetLinkError if the port id of widget is not expected.
        """
        if widget.audio_port.port_id != port_id:
            raise WidgetLinkError(
                    'Link %s expects a %s widget, but gets a %s widget' % (
                            self.name, port_id, widget.audio_port.port_id))


    def connect(self, source, sink):
        """Connects source widget to sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        self._plug_input(source)
        self._plug_output(sink)


    def disconnect(self, source, sink):
        """Disconnects source widget from sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        self._unplug_input(source)
        self._unplug_output(sink)


class AudioBusLink(WidgetLink):
    """The abstraction of widget link using audio bus on audio board.

    This class handles the Audio bus routing.

    Properties:
        _audio_bus: An AudioBus object.

    """
    def __init__(self, audio_bus):
        """Initializes an AudioBusLink.

        @param audio_bus: An AudioBus object.
        """
        super(AudioBusLink, self).__init__()
        self._audio_bus = audio_bus
        logging.debug('Create an AudioBusLink with bus index %d',
                      audio_bus.bus_index)


    def _plug_input(self, widget):
        """Plugs input of audio bus to the widget.

        @param widget: An AudioWidget object.

        """
        self._audio_bus.connect(widget.audio_port.port_id)

        logging.info(
                'Plugged audio board bus %d input to %s',
                self._audio_bus.bus_index, widget.audio_port)


    def _unplug_input(self, widget):
        """Unplugs input of audio bus from the widget.

        @param widget: An AudioWidget object.

        """
        self._audio_bus.disconnect(widget.audio_port.port_id)

        logging.info(
                'Unplugged audio board bus %d input from %s',
                self._audio_bus.bus_index, widget.audio_port)


    def _plug_output(self, widget):
        """Plugs output of audio bus to the widget.

        @param widget: An AudioWidget object.

        """
        self._audio_bus.connect(widget.audio_port.port_id)

        logging.info(
                'Plugged audio board bus %d output to %s',
                self._audio_bus.bus_index, widget.audio_port)


    def _unplug_output(self, widget):
        """Unplugs output of audio bus from the widget.

        @param widget: An AudioWidget object.

        """
        self._audio_bus.disconnect(widget.audio_port.port_id)
        logging.info(
                'Unplugged audio board bus %d output from %s',
                self._audio_bus.bus_index, widget.audio_port)


    def disconnect_audio_bus(self):
        """Disconnects all audio ports from audio bus.

        A snapshot of audio bus is retained so we can reconnect audio bus
        later.
        This method is useful when user wants to let Cros device detects
        audio jack after this link is connected. Some Cros devices
        have sensitive audio jack detection mechanism such that plugger of
        audio board can only be detected when audio bus is disconnected.

        """
        self._audio_bus_snapshot = self._audio_bus.get_snapshot()
        self._audio_bus.clear()


    def reconnect_audio_bus(self):
        """Reconnects audio ports to audio bus using snapshot."""
        self._audio_bus.restore_snapshot(self._audio_bus_snapshot)


class AudioBusToChameleonLink(AudioBusLink):
    """The abstraction for bus on audio board that is connected to Chameleon."""
    # This is the default channel map for 2-channel data recorded on
    # Chameleon through audio board.
    _DEFAULT_CHANNEL_MAP = [1, 0, None, None, None, None, None, None]

    def __init__(self, *args, **kwargs):
        super(AudioBusToChameleonLink, self).__init__(
            *args, **kwargs)
        self.name = ('Audio board bus %s to Chameleon' %
                     self._audio_bus.bus_index)
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        logging.debug(
                'Create an AudioBusToChameleonLink named %s with '
                'channel map %r', self.name, self.channel_map)


class AudioBusChameleonToPeripheralLink(AudioBusLink):
    """The abstraction for audio bus connecting Chameleon to peripheral."""
    # This is the channel map which maps 2-channel data at peripehral speaker
    # to 8 channel data at Chameleon.
    # The left channel at speaker comes from the second channel at Chameleon.
    # The right channel at speaker comes from the first channel at Chameleon.
    # Other channels at Chameleon are neglected.
    _DEFAULT_CHANNEL_MAP = [1, 0]

    def __init__(self, *args, **kwargs):
        super(AudioBusChameleonToPeripheralLink, self).__init__(
              *args, **kwargs)
        self.name = 'Audio board bus %s to peripheral' % self._audio_bus.bus_index
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        logging.debug(
                'Create an AudioBusToPeripheralLink named %s with '
                'channel map %r', self.name, self.channel_map)


class AudioBusToCrosLink(AudioBusLink):
    """The abstraction for audio bus that is connected to Cros device."""
    # This is the default channel map for 1-channel data recorded on
    # Cros device.
    _DEFAULT_CHANNEL_MAP = [0]

    def __init__(self, *args, **kwargs):
        super(AudioBusToCrosLink, self).__init__(
            *args, **kwargs)
        self.name = 'Audio board bus %s to Cros' % self._audio_bus.bus_index
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        logging.debug(
                'Create an AudioBusToCrosLink named %s with '
                'channel map %r', self.name, self.channel_map)


class USBWidgetLink(WidgetLink):
    """The abstraction for USB Cable."""

    # This is the default channel map for 2-channel data
    _DEFAULT_CHANNEL_MAP = [0, 1]
    # Wait some time for Cros device to detect USB has been plugged.
    _DELAY_AFTER_PLUGGING_SECS = 2.0

    def __init__(self, usb_ctrl):
        """Initializes a USBWidgetLink.

        @param usb_ctrl: A USBController object.

        """
        super(USBWidgetLink, self).__init__()
        self.name = 'USB Cable'
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        self._usb_ctrl = usb_ctrl
        logging.debug(
                'Create a USBWidgetLink. Do nothing because USB cable'
                ' is dedicated')


    def connect(self, source, sink):
        """Connects source widget to sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        source.handler.plug()
        sink.handler.plug()
        time.sleep(self._DELAY_AFTER_PLUGGING_SECS)


    def disconnect(self, source, sink):
        """Disconnects source widget from sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        source.handler.unplug()
        sink.handler.unplug()


class USBToCrosWidgetLink(USBWidgetLink):
    """The abstraction for the USB cable connected to the Cros device."""

    def __init__(self, *args, **kwargs):
        """Initializes a USBToCrosWidgetLink."""
        super(USBToCrosWidgetLink, self).__init__(*args, **kwargs)
        self.name = 'USB Cable to Cros'
        logging.debug('Create a USBToCrosWidgetLink: %s', self.name)


class USBToChameleonWidgetLink(USBWidgetLink):
    """The abstraction for the USB cable connected to the Chameleon device."""

    def __init__(self, *args, **kwargs):
        """Initializes a USBToChameleonWidgetLink."""
        super(USBToChameleonWidgetLink, self).__init__(*args, **kwargs)
        self.name = 'USB Cable to Chameleon'
        logging.debug('Create a USBToChameleonWidgetLink: %s', self.name)


class HDMIWidgetLink(WidgetLink):
    """The abstraction for HDMI cable."""

    # This is the default channel map for 2-channel data recorded on
    # Chameleon through HDMI cable.
    _DEFAULT_CHANNEL_MAP = [1, 0, None, None, None, None, None, None]
    _DELAY_AFTER_PLUG_SECONDS = 6

    def __init__(self, cros_host):
        """Initializes a HDMI widget link.

        @param cros_host: A CrosHost object to access Cros device.

        """
        super(HDMIWidgetLink, self).__init__()
        self.name = 'HDMI cable'
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        self._cros_host = cros_host
        logging.debug(
                'Create an HDMIWidgetLink. Do nothing because HDMI cable'
                ' is dedicated')


    # TODO(cychiang) remove this when issue crbug.com/450101 is fixed.
    def _correction_plug_unplug_for_audio(self, handler):
        """Plugs/unplugs several times for Cros device to detect audio.

        For issue crbug.com/450101, Exynos HDMI driver has problem recognizing
        HDMI audio, while display can be detected. Do several plug/unplug and
        wait as a workaround. Note that HDMI port will be in unplugged state
        in the end if extra plug/unplug is needed.
        We have seen this on Intel device(cyan, celes) too.

        @param handler: A ChameleonHDMIInputWidgetHandler.

        """
        board = self._cros_host.get_board().split(':')[1]
        if board in ['cyan', 'celes', 'lars']:
            logging.info('Need extra plug/unplug on board %s', board)
            for _ in xrange(3):
                handler.plug()
                time.sleep(3)
                handler.unplug()
                time.sleep(3)


    def connect(self, source, sink):
        """Connects source widget to sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        sink.handler.set_edid_for_audio()
        self._correction_plug_unplug_for_audio(sink.handler)
        sink.handler.plug()
        time.sleep(self._DELAY_AFTER_PLUG_SECONDS)


    def disconnect(self, source, sink):
        """Disconnects source widget from sink widget.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        sink.handler.unplug()
        sink.handler.restore_edid()


class BluetoothWidgetLink(WidgetLink):
    """The abstraction for bluetooth link between Cros device and bt module."""
    # The delay after connection for cras to process the bluetooth connection
    # event and enumerate the bluetooth nodes.
    _DELAY_AFTER_CONNECT_SECONDS = 15

    def __init__(self, bt_adapter, audio_board_bt_ctrl, mac_address):
        """Initializes a BluetoothWidgetLink.

        @param bt_adapter: A BluetoothDevice object to control bluetooth
                           adapter on Cros device.
        @param audio_board_bt_ctrl: A BlueoothController object to control
                                    bluetooth module on audio board.
        @param mac_address: The MAC address of bluetooth module on audio board.

        """
        super(BluetoothWidgetLink, self).__init__()
        self._bt_adapter = bt_adapter
        self._audio_board_bt_ctrl = audio_board_bt_ctrl
        self._mac_address = mac_address


    def connect(self, source, sink):
        """Customizes the connecting sequence for bluetooth widget link.

        We need to enable bluetooth module first, then start connecting
        sequence from bluetooth adapter.
        The arguments source and sink are not used because BluetoothWidgetLink
        already has the access to bluetooth module on audio board and
        bluetooth adapter on Cros device.

        @param source: An AudioWidget object.
        @param sink: An AudioWidget object.

        """
        self.enable_bluetooth_module()
        self._adapter_connect_sequence()
        time.sleep(self._DELAY_AFTER_CONNECT_SECONDS)


    def disconnect(self, source, sink):
        """Customizes the disconnecting sequence for bluetooth widget link.

        The arguments source and sink are not used because BluetoothWidgetLink
        already has the access to bluetooth module on audio board and
        bluetooth adapter on Cros device.

        @param source: An AudioWidget object (unused).
        @param sink: An AudioWidget object (unused).

        """
        self.disable_bluetooth_module()
        self.adapter_disconnect_module()


    def enable_bluetooth_module(self):
        """Reset bluetooth module if it is not enabled."""
        self._audio_board_bt_ctrl.reset()


    def disable_bluetooth_module(self):
        """Disables bluetooth module if it is enabled."""
        if self._audio_board_bt_ctrl.is_enabled():
            self._audio_board_bt_ctrl.disable()


    def _adapter_connect_sequence(self):
        """Scans, pairs, and connects bluetooth module to bluetooth adapter.

        If the device is already connected, skip the connection sequence.

        """
        if self._bt_adapter.device_is_connected(self._mac_address):
            logging.debug(
                    '%s is already connected, skip the connection sequence',
                    self._mac_address)
            return
        chameleon_bluetooth_audio.connect_bluetooth_module_full_flow(
                self._bt_adapter, self._mac_address)


    def _disable_adapter(self):
        """Turns off bluetooth adapter."""
        self._bt_adapter.reset_off()


    def adapter_connect_module(self):
        """Controls adapter to connect bluetooth module."""
        chameleon_bluetooth_audio.connect_bluetooth_module(
                self._bt_adapter, self._mac_address)

    def adapter_disconnect_module(self):
        """Controls adapter to disconnect bluetooth module."""
        self._bt_adapter.disconnect_device(self._mac_address)


class BluetoothHeadphoneWidgetLink(BluetoothWidgetLink):
    """The abstraction for link from Cros device headphone to bt module Rx."""

    def __init__(self, *args, **kwargs):
        """Initializes a BluetoothHeadphoneWidgetLink."""
        super(BluetoothHeadphoneWidgetLink, self).__init__(*args, **kwargs)
        self.name = 'Cros bluetooth headphone to peripheral bluetooth module'
        logging.debug('Create an BluetoothHeadphoneWidgetLink: %s', self.name)


class BluetoothMicWidgetLink(BluetoothWidgetLink):
    """The abstraction for link from bt module Tx to Cros device microphone."""

    # This is the default channel map for 1-channel data recorded on
    # Cros device using bluetooth microphone.
    _DEFAULT_CHANNEL_MAP = [0]

    def __init__(self, *args, **kwargs):
        """Initializes a BluetoothMicWidgetLink."""
        super(BluetoothMicWidgetLink, self).__init__(*args, **kwargs)
        self.name = 'Peripheral bluetooth module to Cros bluetooth mic'
        self.channel_map = self._DEFAULT_CHANNEL_MAP
        logging.debug('Create an BluetoothMicWidgetLink: %s', self.name)


class WidgetBinderChain(object):
    """Abstracts a chain of binders.

    This class supports connect, disconnect, release, just like WidgetBinder,
    except that this class handles a chain of WidgetBinders.

    """
    def __init__(self, binders):
        """Initializes a WidgetBinderChain.

        @param binders: A list of WidgetBinder.

        """
        self._binders = binders


    def connect(self):
        """Asks all binders to connect."""
        for binder in self._binders:
            binder.connect()


    def disconnect(self):
        """Asks all binders to disconnect."""
        for binder in self._binders:
            binder.disconnect()


    def release(self):
        """Asks all binders to release."""
        for binder in self._binders:
            binder.release()


    def get_binders(self):
        """Returns all the binders.

        @returns: A list of binders.

        """
        return self._binders
