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

import logging
import os

from autotest_lib.client.bin import test
from autotest_lib.client.bin import utils
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import chrome
from autotest_lib.client.cros.video import helper_logger
from autotest_lib.client.cros.audio import audio_helper
from autotest_lib.client.cros.audio import cras_utils

# Suppress the media Permission Dialog.
EXTRA_BROWSER_ARGS = [
    '--use-fake-ui-for-media-stream',  # Suppress the Permission Dialog
    '--use-fake-device-for-media-stream'  # Use fake audio & video
]

AUDIO_LOOPBACK_PAGE = 'audio_loopback.html'

# The test's runtime.
TEST_RUNTIME_SECONDS = 10

# Number of peer connections to use.
NUM_PEER_CONNECTIONS = 1

# Polling timeout.
TIMEOUT = TEST_RUNTIME_SECONDS + 10


class audio_WebRtcAudioLoopback(test.test):
    """Tests a WebRTC call with a fake audio."""
    version = 1

    def start_test(self, cr, recorded_file):
        """Opens the WebRTC audio loopback page and records audio output.

        @param cr: Autotest Chrome instance.
        @param recorded_file: File to recorder the audio output to.
        """
        cr.browser.platform.SetHTTPServerDirectories(self.bindir)

        self.tab = cr.browser.tabs[0]
        self.tab.Navigate(cr.browser.platform.http_server.UrlOf(
            os.path.join(self.bindir, AUDIO_LOOPBACK_PAGE)))
        self.tab.WaitForDocumentReadyStateToBeComplete()
        self.tab.EvaluateJavaScript(
            "run(%d, %d)" % (TEST_RUNTIME_SECONDS, NUM_PEER_CONNECTIONS))
        self.wait_for_active_stream_count(1)
        cras_utils.capture(recorded_file, duration=TEST_RUNTIME_SECONDS)

    def wait_test_completed(self, timeout_secs):
        """Waits until the test is done.

        @param timeout_secs Max time to wait in seconds.

        @raises TestError on timeout, or javascript eval fails.
        """
        def _test_done():
            status = self.tab.EvaluateJavaScript('testRunner.getStatus()')
            logging.info(status)
            return status == 'ok-done'

        utils.poll_for_condition(
                _test_done, timeout=timeout_secs, sleep_interval=1,
                desc='audio.html reports itself as finished')

    @staticmethod
    def wait_for_active_stream_count(expected_count):
        """Waits for the expected number of active streams.

        @param expected_count: expected count of active streams.
        """
        utils.poll_for_condition(
            lambda: cras_utils.get_active_stream_count() == expected_count,
            exception=error.TestError(
                'Timeout waiting active stream count to become "%d",'
                'current value is "%d"' % (
                    expected_count, cras_utils.get_active_stream_count())))

    @helper_logger.video_log_wrapper
    def run_once(self):
        """Runs the audio_WebRtcAudioLoopback test."""
        # Record a sample of "silence" to use as a noise profile.
        noise_file = os.path.join(self.resultsdir, 'cras_noise.wav')
        cras_utils.capture(noise_file, duration=1)

        # Create a file for the audio recording.
        recorded_file = os.path.join(self.resultsdir, 'cras_recorded.wav')

        self.wait_for_active_stream_count(0)
        with chrome.Chrome(extra_browser_args=EXTRA_BROWSER_ARGS +\
                            [helper_logger.chrome_vmodule_flag()],
                           init_network_controller=True) as cr:
            self.start_test(cr, recorded_file)
            self.wait_test_completed(TIMEOUT)
            self.print_result(recorded_file, noise_file)

    def print_result(self, recorded_file, noise_file):
        """Prints results unless status is different from ok-done.

        @raises TestError if the test failed outright.
        @param recorded_file: File to recorder the audio output to.
        @param noise_file: Noise recording, used for comparison.
        """
        status = self.tab.EvaluateJavaScript('testRunner.getStatus()')
        if status != 'ok-done':
            raise error.TestFail('Failed: %s' % status)

        results = self.tab.EvaluateJavaScript('testRunner.getResults()')
        logging.info('runTimeSeconds: %.2f', results['runTimeSeconds'])

        rms_value = audio_helper.reduce_noise_and_get_rms(
                recorded_file, noise_file)[0]
        logging.info('rms_value: %f', rms_value)
        self.output_perf_value(
                description='rms_value',
                value=rms_value,
                units='', higher_is_better=True)

