# 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 is a server side audio test using the Chameleon board."""

from __future__ import print_function

import logging
import os
import time
import threading

from autotest_lib.client.common_lib import error
from autotest_lib.client.cros.chameleon import audio_test_utils
from autotest_lib.client.cros.chameleon import chameleon_audio_helper
from autotest_lib.client.cros.chameleon import chameleon_audio_ids
from autotest_lib.server.cros.audio import audio_test
from autotest_lib.server.cros.multimedia import remote_facade_factory


class audio_AudioAfterSuspend(audio_test.AudioTest):
    """Server side audio test.

    This test talks to a Chameleon board and a Cros device to verify
    audio function of the Cros device.

    """
    version = 1
    DELAY_BEFORE_RECORD_SECONDS = 0.5
    RECORD_SECONDS = 5
    RESUME_TIMEOUT_SECS = 60
    SHORT_WAIT = 2
    SUSPEND_SECONDS = 40


    def action_plug_jack(self, plug_state):
        """Calls the audio interface API and plugs/unplugs.

        @param plug_state: plug state to switch to

        """
        logging.debug('Plugging' if plug_state else 'Unplugging')
        jack_plugger = self.audio_board.get_jack_plugger()

        # It is not required for the test to have jack plugger.
        # We'll ignore the plug/unplug action and assume the target device
        # is all time plugged/unplugged if there is no jack plugger.
        if jack_plugger is None:
            logging.debug('Jack plugger is NOT present!')
            return

        if plug_state:
            jack_plugger.plug()
            audio_test_utils.check_plugged_nodes_contain(self.audio_facade,
                                                         self.audio_nodes)
        else:
            jack_plugger.unplug()
        time.sleep(self.SHORT_WAIT)


    def action_suspend(self, suspend_time=SUSPEND_SECONDS):
        """Calls the host method suspend.

        @param suspend_time: time to suspend the device for.

        """
        self.host.suspend(suspend_time=suspend_time)


    def suspend_resume(self, plugged_before_suspend, plugged_after_suspend,
                                plugged_before_resume, test_case):
        """Performs the mix of suspend/resume and plug/unplug

        @param plugged_before_suspend: plug state before suspend
        @param plugged_after_suspend: plug state after suspend
        @param plugged_before_resume: plug state before resume
        @param test_case: string identifying test case sequence

        """

        # Suspend
        boot_id = self.host.get_boot_id()
        thread = threading.Thread(target=self.action_suspend)
        thread.start()
        try:
            self.host.test_wait_for_sleep(3 * self.SUSPEND_SECONDS / 4)
        except error.TestFail as ex:
            self.errors.append("%s - %s" % (test_case, str(ex)))

        # Plugged after suspended
        self.action_plug_jack(plugged_after_suspend)

        # Plugged before resumed
        self.action_plug_jack(plugged_before_resume)
        try:
            self.host.test_wait_for_resume(boot_id, self.RESUME_TIMEOUT_SECS)
        except error.TestFail as ex:
            self.errors.append("%s - %s" % (test_case, str(ex)))


    def check_correct_audio_node_selected(self):
        """Checks the node selected by Cras is correct."""
        audio_test_utils.check_audio_nodes(self.audio_facade, self.audio_nodes)


    def play_and_record(self, source_widget, recorder_widget):
        """Plays and records audio

        @param source_widget: widget to do the playback
        @param recorder_widget: widget to do the recording

        """
        audio_test_utils.dump_cros_audio_logs(
                self.host, self.audio_facade, self.resultsdir,
                'before_playback')

        self.check_correct_audio_node_selected()

        # Play, wait for some time, and then start recording.
        # This is to avoid artifact caused by codec initialization.
        source_widget.set_playback_data(self.golden_file)
        logging.debug('Start playing %s', self.golden_file.path)
        source_widget.start_playback()

        time.sleep(self.DELAY_BEFORE_RECORD_SECONDS)
        logging.debug('Start recording.')
        recorder_widget.start_recording()

        time.sleep(self.RECORD_SECONDS)

        recorder_widget.stop_recording()
        logging.debug('Stopped recording.')

        audio_test_utils.dump_cros_audio_logs(
                self.host, self.audio_facade, self.resultsdir,
                'after_recording')

        recorder_widget.read_recorded_binary()


    def save_and_check_data(self, recorder_widget):
        """Saves and checks the data from the recorder

        @param recorder_widget: recorder widget to save data from

        @returns (success, error_message): success is True if audio comparison
                                           is successful, False otherwise.
                                           error_message contains the error
                                           message.

        """
        recorded_file = os.path.join(self.resultsdir, "recorded.raw")
        logging.debug('Saving recorded data to %s', recorded_file)
        recorder_widget.save_file(recorded_file)

        # Removes the beginning of recorded data. This is to avoid artifact
        # caused by codec initialization in the beginning of
        # recording.
        recorder_widget.remove_head(2.0)

        # Removes noise by a lowpass filter.
        recorder_widget.lowpass_filter(self.low_pass_freq)
        recorded_file = os.path.join(self.resultsdir,
                                     "recorded_filtered.raw")
        logging.debug('Saving filtered data to %s', recorded_file)
        recorder_widget.save_file(recorded_file)

        # Compares data by frequency and returns the result.
        try:
            audio_test_utils.check_recorded_frequency(
                    self.golden_file, recorder_widget,
                    second_peak_ratio=self.second_peak_ratio,
                    ignore_frequencies=self.ignore_frequencies)
        except error.TestFail as e:
            return (False, e)

        return (True, None)


    def run_once(self, host, audio_nodes, golden_data,
                 bind_from=None, bind_to=None,
                 source=None, recorder=None, plug_status=None):
        """Runs the test main workflow

        @param host: A host object representing the DUT.
        @param audio_nodes: audio nodes supposed to be selected.
        @param golden_data: audio file and low pass filter frequency
           the audio file should be test data defined in audio_test_data
        @param bind_from: audio originating entity to be binded
            should be defined in chameleon_audio_ids
        @param bind_to: audio directed_to entity to be binded
            should be defined in chameleon_audio_ids
        @param source: source widget entity
            should be defined in chameleon_audio_ids
        @param recorder: recorder widget entity
            should be defined in chameleon_audio_ids
        @param plug_status: audio channel plug unplug sequence

        """
        if ((bind_from == chameleon_audio_ids.CrosIds.HEADPHONE or
            bind_to == chameleon_audio_ids.CrosIds.EXTERNAL_MIC) and
            not audio_test_utils.has_audio_jack(self.host)):
            raise error.TestNAError(
                    'No audio jack for the DUT.'
                    ' Confirm swarming bot dimension and control file'
                    ' dependency for audio jack is matching.'
                    ' For new boards, has_audio_jack might need to be updated.'
            )

        if (recorder == chameleon_audio_ids.CrosIds.INTERNAL_MIC and
            not audio_test_utils.has_internal_microphone(host)):
            return

        if (source == chameleon_audio_ids.CrosIds.SPEAKER and
            not audio_test_utils.has_internal_speaker(host)):
            return

        self.host = host
        self.audio_nodes = audio_nodes

        self.second_peak_ratio = audio_test_utils.get_second_peak_ratio(
                source_id=source,
                recorder_id=recorder)

        self.ignore_frequencies = None
        if (source == chameleon_audio_ids.CrosIds.SPEAKER
                    or bind_to == chameleon_audio_ids.CrosIds.EXTERNAL_MIC):
            self.ignore_frequencies = [50, 60]

        self.errors = []
        self.golden_file, self.low_pass_freq = golden_data
        chameleon_board = self.host.chameleon
        self.factory = remote_facade_factory.RemoteFacadeFactory(
                self.host, results_dir=self.resultsdir)
        self.audio_facade = self.factory.create_audio_facade()
        chameleon_board.setup_and_reset(self.outputdir)
        widget_factory = chameleon_audio_helper.AudioWidgetFactory(
                self.factory, host)

        # Two widgets are binded in the factory if necessary
        binder_widget = None
        bind_from_widget = None
        bind_to_widget = None
        if bind_from != None and bind_to != None:
            bind_from_widget = widget_factory.create_widget(bind_from)
            bind_to_widget = widget_factory.create_widget(bind_to)
            binder_widget = widget_factory.create_binder(bind_from_widget,
                                                         bind_to_widget)

        # Additional widgets that could be part of the factory
        if source == None:
            source_widget = bind_from_widget
        else:
            source_widget = widget_factory.create_widget(source)
        if recorder == None:
            recorder_widget = bind_to_widget
        else:
            recorder_widget = widget_factory.create_widget(recorder)

        self.audio_board = chameleon_board.get_audio_board()

        test_index = 0
        for (plugged_before_suspend, plugged_after_suspend, plugged_before_resume,
             plugged_after_resume) in plug_status:
            test_index += 1

            test_case = ('TEST CASE %d: %s > suspend > %s > %s > resume > %s' %
                (test_index, 'PLUG' if plugged_before_suspend else 'UNPLUG',
                 'PLUG' if plugged_after_suspend else 'UNPLUG',
                 'PLUG' if plugged_before_resume else 'UNPLUG',
                 'PLUG' if plugged_after_resume else 'UNPLUG'))
            logging.info(test_case)

            # Plugged status before suspended
            self.action_plug_jack(plugged_before_suspend)

            self.suspend_resume(plugged_before_suspend,
                                plugged_after_suspend,
                                plugged_before_resume,
                                test_case)

            # Active (plugged for external) state after resume
            self.action_plug_jack(plugged_after_resume)

            # Explicitly select the node as there is a known issue
            # that the selected node might change after a suspension.
            # We should remove this after the issue is addressed(crbug:987529).
            self.audio_facade.set_selected_node_types(self.audio_nodes[0],
                                                      self.audio_nodes[1])

            if binder_widget != None:
                with chameleon_audio_helper.bind_widgets(binder_widget):
                    self.play_and_record(source_widget, recorder_widget)
            else:
                self.play_and_record(source_widget, recorder_widget)

            success, error_message = self.save_and_check_data(recorder_widget)
            if not success:
                self.errors.append('%s: Comparison failed: %s' %
                                   (test_case, error_message))

        if self.errors:
            raise error.TestFail('; '.join(set(self.errors)))
