# 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 framework for audio tests using chameleon."""

import logging
from contextlib import contextmanager

from autotest_lib.client.cros.chameleon import audio_widget
from autotest_lib.client.cros.chameleon import audio_widget_arc
from autotest_lib.client.cros.chameleon import audio_widget_link
from autotest_lib.server.cros.bluetooth import bluetooth_device
from autotest_lib.client.cros.chameleon import chameleon_audio_ids as ids

class AudioPort(object):
    """
    This class abstracts an audio port in audio test framework. A port is
    identified by its host and interface. Available hosts and interfaces
    are listed in chameleon_audio_ids.

    Properties:
        port_id: The port id defined in chameleon_audio_ids.
        host: The host of this audio port, e.g. 'Chameleon', 'Cros',
              'Peripheral'.
        interface: The interface of this audio port, e.g. 'HDMI', 'Headphone'.
        role: The role of this audio port, that is, 'source' or
              'sink'. Note that bidirectional interface like 3.5mm
              jack is separated to two interfaces 'Headphone' and
             'External Mic'.

    """
    def __init__(self, port_id):
        """Initialize an AudioPort with port id string.

        @param port_id: A port id string defined in chameleon_audio_ids.

        """
        logging.debug('Creating AudioPort with port_id: %s', port_id)
        self.port_id = port_id
        self.host = ids.get_host(port_id)
        self.interface = ids.get_interface(port_id)
        self.role = ids.get_role(port_id)
        logging.debug('Created AudioPort: %s', self)


    def __str__(self):
        """String representation of audio port.

        @returns: The string representation of audio port which is composed by
                  host, interface, and role.

        """
        return '( %s | %s | %s )' % (
                self.host, self.interface, self.role)


class AudioLinkFactoryError(Exception):
    """Error in AudioLinkFactory."""
    pass


class AudioLinkFactory(object):
    """
    This class provides method to create link that connects widgets.
    This is used by AudioWidgetFactory when user wants to create binder for
    widgets.

    Properties:
        _audio_bus_links: A dict containing mapping from index number
                          to object of AudioBusLink's subclass.
        _audio_board: An AudioBoard object to access Chameleon
                      audio board functionality.

    """

    # Maps pair of widgets to widget link of different type.
    LINK_TABLE = {
        (ids.CrosIds.HDMI, ids.ChameleonIds.HDMI):
                audio_widget_link.HDMIWidgetLink,
        (ids.CrosIds.HEADPHONE, ids.ChameleonIds.LINEIN):
                audio_widget_link.AudioBusToChameleonLink,
        (ids.ChameleonIds.LINEOUT, ids.CrosIds.EXTERNAL_MIC):
                audio_widget_link.AudioBusToCrosLink,
        (ids.ChameleonIds.LINEOUT, ids.PeripheralIds.SPEAKER):
                audio_widget_link.AudioBusChameleonToPeripheralLink,
        (ids.PeripheralIds.MIC, ids.ChameleonIds.LINEIN):
                audio_widget_link.AudioBusToChameleonLink,
        (ids.PeripheralIds.BLUETOOTH_DATA_RX,
         ids.ChameleonIds.LINEIN):
                audio_widget_link.AudioBusToChameleonLink,
        (ids.ChameleonIds.LINEOUT,
         ids.PeripheralIds.BLUETOOTH_DATA_TX):
                audio_widget_link.AudioBusChameleonToPeripheralLink,
        (ids.CrosIds.BLUETOOTH_HEADPHONE,
         ids.PeripheralIds.BLUETOOTH_DATA_RX):
                audio_widget_link.BluetoothHeadphoneWidgetLink,
        (ids.PeripheralIds.BLUETOOTH_DATA_TX,
         ids.CrosIds.BLUETOOTH_MIC):
                audio_widget_link.BluetoothMicWidgetLink,
        (ids.CrosIds.USBOUT, ids.ChameleonIds.USBIN):
                audio_widget_link.USBToChameleonWidgetLink,
        (ids.ChameleonIds.USBOUT, ids.CrosIds.USBIN):
                audio_widget_link.USBToCrosWidgetLink,
        # TODO(cychiang): Add link for other widget pairs.
    }

    def __init__(self, cros_host):
        """Initializes an AudioLinkFactory.

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

        """
        # There are two audio buses on audio board. Initializes these links
        # to None. They may be changed to objects of AudioBusLink's subclass.
        self._audio_bus_links = {1: None, 2: None}
        self._cros_host = cros_host
        self._chameleon_board = cros_host.chameleon
        self._audio_board = self._chameleon_board.get_audio_board()
        self._bluetooth_device = None
        self._usb_ctrl = None


    def _acquire_audio_bus_index(self):
        """Acquires an available audio bus index that is not occupied yet.

        @returns: A number.

        @raises: AudioLinkFactoryError if there is no available
                 audio bus.
        """
        for index, bus in self._audio_bus_links.iteritems():
            if not (bus and bus.occupied):
                return index

        raise AudioLinkFactoryError('No available audio bus')


    def create_link(self, source, sink):
        """Creates a widget link for two audio widgets.

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

        @returns: An object of WidgetLink's subclass.

        @raises: AudioLinkFactoryError if there is no link between
            source and sink.

        """
        # Finds the available link types from LINK_TABLE.
        link_type = self.LINK_TABLE.get((source.port_id, sink.port_id), None)
        if not link_type:
            raise AudioLinkFactoryError(
                    'No supported link between %s and %s' % (
                            source.port_id, sink.port_id))

        # There is only one dedicated HDMI cable, just use it.
        if link_type == audio_widget_link.HDMIWidgetLink:
            link = audio_widget_link.HDMIWidgetLink(self._cros_host)

        # Acquires audio bus if there is available bus.
        # Creates a bus of AudioBusLink's subclass that is more
        # specific than AudioBusLink.
        # Controls this link using AudioBus object obtained from AudioBoard
        # object.
        elif issubclass(link_type, audio_widget_link.AudioBusLink):
            bus_index = self._acquire_audio_bus_index()
            link = link_type(self._audio_board.get_audio_bus(bus_index))
            self._audio_bus_links[bus_index] = link
        elif issubclass(link_type, audio_widget_link.BluetoothWidgetLink):
            # To connect bluetooth adapter on Cros device to bluetooth module on
            # chameleon board, we need to access bluetooth adapter on Cros host
            # using BluetoothDevice, and access bluetooth module on
            # audio board using BluetoothController.

            # Initializes a BluetoothDevice object if needed. And reuse this
            # object for future bluetooth link usage.
            if not self._bluetooth_device:
                self._bluetooth_device = bluetooth_device.BluetoothDevice(
                        self._cros_host)
            link = link_type(
                    self._bluetooth_device,
                    self._chameleon_board.get_bluetooth_ref_controller(),
                    self._chameleon_board.get_bluetooth_a2dp_sink().GetLocalBluetoothAddress())
        elif issubclass(link_type, audio_widget_link.USBWidgetLink):
            # Aside from managing connection between USB audio gadget driver on
            # Chameleon with Cros device, USBWidgetLink also handles changing
            # the gadget driver's configurations, through the USBController that
            # is passed to it at initialization.
            if not self._usb_ctrl:
                self._usb_ctrl = self._chameleon_board.get_usb_controller()

            link = link_type(self._usb_ctrl)
        else:
            raise NotImplementedError('Link %s is not implemented' % link_type)

        return link


class AudioWidgetFactoryError(Exception):
    """Error in AudioWidgetFactory."""
    pass


class AudioWidgetFactory(object):
    """
    This class provides methods to create widgets and binder of widgets.
    User can use binder to setup audio paths. User can use widgets to control
    record/playback on different ports on Cros device or Chameleon.

    Properties:
        _audio_facade: An AudioFacadeRemoteAdapter to access Cros device audio
                       functionality. This is created by the
                       'factory' argument passed to the constructor.
        _display_facade: A DisplayFacadeRemoteAdapter to access Cros device
                         display functionality. This is created by the
                         'factory' argument passed to the constructor.
        _system_facade: A SystemFacadeRemoteAdapter to access Cros device
                         system functionality. This is created by the
                         'factory' argument passed to the constructor.
        _chameleon_board: A ChameleonBoard object to access Chameleon
                          functionality.
        _link_factory: An AudioLinkFactory that creates link for widgets.

    """
    def __init__(self, factory, cros_host):
        """Initializes a AudioWidgetFactory

        @param factory: A facade factory to access Cros device functionality.
                        Currently only audio facade is used, but we can access
                        other functionalities including display and video by
                        facades created by this facade factory.
        @param cros_host: A CrosHost object to access Cros device.

        """
        self._audio_facade = factory.create_audio_facade()
        self._display_facade = factory.create_display_facade()
        self._system_facade = factory.create_system_facade()
        self._usb_facade = factory.create_usb_facade()
        self._cros_host = cros_host
        self._chameleon_board = cros_host.chameleon
        self._link_factory = AudioLinkFactory(cros_host)


    def create_widget(self, port_id, use_arc=False):
        """Creates a AudioWidget given port id string.

        @param port_id: A port id string defined in chameleon_audio_ids.
        @param use_arc: For Cros widget, select if audio path exercises ARC.
                        Currently only input widget is supported.

        @returns: An AudioWidget that is actually a
                  (Chameleon/Cros/Peripheral)(Input/Output)Widget.

        """
        def _create_chameleon_handler(audio_port):
            """Creates a ChameleonWidgetHandler for a given AudioPort.

            @param audio_port: An AudioPort object.

            @returns: A Chameleon(Input/Output)WidgetHandler depending on
                      role of audio_port.

            """
            if audio_port.role == 'sink':
                if audio_port.port_id == ids.ChameleonIds.HDMI:
                    return audio_widget.ChameleonHDMIInputWidgetHandler(
                            self._chameleon_board, audio_port.interface,
                            self._display_facade)
                else:
                    return audio_widget.ChameleonInputWidgetHandler(
                            self._chameleon_board, audio_port.interface)
            else:
                if audio_port.port_id == ids.ChameleonIds.LINEOUT:
                    return audio_widget.ChameleonLineOutOutputWidgetHandler(
                            self._chameleon_board, audio_port.interface)
                else:
                    return audio_widget.ChameleonOutputWidgetHandler(
                            self._chameleon_board, audio_port.interface)


        def _create_cros_handler(audio_port):
            """Creates a CrosWidgetHandler for a given AudioPort.

            @param audio_port: An AudioPort object.

            @returns: A Cros(Input/Output)WidgetHandler depending on
                      role of audio_port.

            """
            is_usb = audio_port.port_id in [ids.CrosIds.USBIN,
                                            ids.CrosIds.USBOUT]
            is_audio_jack = audio_port.port_id in [ids.CrosIds.HEADPHONE,
                                                   ids.CrosIds.EXTERNAL_MIC]
            is_internal_mic = audio_port.port_id == ids.CrosIds.INTERNAL_MIC
            is_hotwording = audio_port.port_id == ids.CrosIds.HOTWORDING

            # Determines the plug handler to be used.
            # By default, the plug handler is DummyPlugHandler.
            # If the port uses audio jack, and there is jack plugger available
            # through audio board, then JackPluggerPlugHandler should be used.
            audio_board = self._chameleon_board.get_audio_board()
            if audio_board:
                jack_plugger = audio_board.get_jack_plugger()
            else:
                jack_plugger = None

            if jack_plugger and is_audio_jack:
                plug_handler = audio_widget.JackPluggerPlugHandler(jack_plugger)
            else:
                plug_handler = audio_widget.DummyPlugHandler()

            if audio_port.role == 'sink':
                if use_arc:
                    return audio_widget_arc.CrosInputWidgetARCHandler(
                            self._audio_facade, plug_handler)
                elif is_usb:
                    return audio_widget.CrosUSBInputWidgetHandler(
                            self._audio_facade, plug_handler)
                elif is_internal_mic:
                    return audio_widget.CrosIntMicInputWidgetHandler(
                            self._audio_facade, plug_handler,
                            self._system_facade)
                elif is_hotwording:
                    return audio_widget.CrosHotwordingWidgetHandler(
                            self._audio_facade, plug_handler,
                            self._system_facade)
                else:
                    return audio_widget.CrosInputWidgetHandler(
                            self._audio_facade, plug_handler)
            else:
                if use_arc:
                    return audio_widget_arc.CrosOutputWidgetARCHandler(
                            self._audio_facade, plug_handler)
                return audio_widget.CrosOutputWidgetHandler(self._audio_facade,
                                                            plug_handler)


        def _create_audio_widget(audio_port, handler):
            """Creates an AudioWidget for given AudioPort using WidgetHandler.

            Creates an AudioWidget with the role of audio_port. Put
            the widget handler into the widget so the widget can handle
            action requests.

            @param audio_port: An AudioPort object.
            @param handler: A WidgetHandler object.

            @returns: An Audio(Input/Output)Widget depending on
                      role of audio_port.

            @raises: AudioWidgetFactoryError if fail to create widget.

            """
            if audio_port.host in ['Chameleon', 'Cros']:
                if audio_port.role == 'sink':
                    return audio_widget.AudioInputWidget(audio_port, handler)
                else:
                    return audio_widget.AudioOutputWidget(audio_port, handler)
            elif audio_port.host == 'Peripheral':
                return audio_widget.PeripheralWidget(audio_port, handler)
            else:
                raise AudioWidgetFactoryError(
                        'The host %s is not valid' % audio_port.host)


        audio_port = AudioPort(port_id)
        if audio_port.host == 'Chameleon':
            handler = _create_chameleon_handler(audio_port)
        elif audio_port.host == 'Cros':
            handler = _create_cros_handler(audio_port)
        elif audio_port.host == 'Peripheral':
            handler = audio_widget.PeripheralWidgetHandler()

        return _create_audio_widget(audio_port, handler)


    def _create_widget_binder(self, source, sink):
        """Creates a WidgetBinder for two AudioWidgets.

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

        @returns: A WidgetBinder object.

        """
        return audio_widget_link.WidgetBinder(
                source, self._link_factory.create_link(source, sink), sink)


    def create_binder(self, *widgets):
        """Creates a WidgetBinder or a WidgetChainBinder for AudioWidgets.

        @param widgets: A list of widgets that should be linked in a chain.

        @returns: A WidgetBinder for two widgets. A WidgetBinderChain object
                  for three or more widgets.

        """
        if len(widgets) == 2:
            return self._create_widget_binder(widgets[0], widgets[1])
        binders = []
        for index in xrange(len(widgets) - 1):
            binders.append(
                    self._create_widget_binder(
                            widgets[index],  widgets[index + 1]))

        return audio_widget_link.WidgetBinderChain(binders)


@contextmanager
def bind_widgets(binder):
    """Context manager for widget binders.

    Connects widgets in the beginning. Disconnects widgets and releases binder
    in the end.

    @param binder: A WidgetBinder object or a WidgetBinderChain object.
                   If binder is None, then do nothing. This is for test user's
                   convenience to reuse test logic among paths using binder
                   and paths not using binder.

    E.g. with bind_widgets(binder):
             do something on widget.

    """
    if not binder:
        yield
    else:
        try:
            binder.connect()
            yield
        finally:
            binder.disconnect()
            binder.release()
