#!/usr/bin/env python
# Copyright (c) 2017 The WebRTC project authors. All Rights Reserved.
#
# Use of this source code is governed by a BSD-style license
# that can be found in the LICENSE file in the root of the source
# tree. An additional intellectual property rights grant can be found
# in the file PATENTS.  All contributing project authors may
# be found in the AUTHORS file in the root of the source tree.
"""
This script is the wrapper that runs the low-bandwidth audio test.

After running the test, post-process steps for calculating audio quality of the
output files will be performed.
"""

import argparse
import collections
import logging
import os
import re
import shutil
import subprocess
import sys

SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
SRC_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, os.pardir, os.pardir))

NO_TOOLS_ERROR_MESSAGE = (
    'Could not find PESQ or POLQA at %s.\n'
    '\n'
    'To fix this run:\n'
    '  python %s %s\n'
    '\n'
    'Note that these tools are Google-internal due to licensing, so in order to '
    'use them you will have to get your own license and manually put them in the '
    'right location.\n'
    'See https://cs.chromium.org/chromium/src/third_party/webrtc/tools_webrtc/'
    'download_tools.py?rcl=bbceb76f540159e2dba0701ac03c514f01624130&l=13')


def _LogCommand(command):
    logging.info('Running %r', command)
    return command


def _ParseArgs():
    parser = argparse.ArgumentParser(
        description='Run low-bandwidth audio tests.')
    parser.add_argument('build_dir',
                        help='Path to the build directory (e.g. out/Release).')
    parser.add_argument('--remove',
                        action='store_true',
                        help='Remove output audio files after testing.')
    parser.add_argument(
        '--android',
        action='store_true',
        help='Perform the test on a connected Android device instead.')
    parser.add_argument('--adb-path',
                        help='Path to adb binary.',
                        default='adb')
    parser.add_argument('--num-retries',
                        default='0',
                        help='Number of times to retry the test on Android.')
    parser.add_argument(
        '--isolated-script-test-perf-output',
        default=None,
        help='Path to store perf results in histogram proto format.')
    parser.add_argument('--extra-test-args',
                        default=[],
                        action='append',
                        help='Extra args to path to the test binary.')

    # Ignore Chromium-specific flags
    parser.add_argument('--test-launcher-summary-output',
                        type=str,
                        default=None)
    args = parser.parse_args()

    return args


def _GetPlatform():
    if sys.platform == 'win32':
        return 'win'
    elif sys.platform == 'darwin':
        return 'mac'
    elif sys.platform.startswith('linux'):
        return 'linux'


def _GetExtension():
    return '.exe' if sys.platform == 'win32' else ''


def _GetPathToTools():
    tools_dir = os.path.join(SRC_DIR, 'tools_webrtc')
    toolchain_dir = os.path.join(tools_dir, 'audio_quality')

    platform = _GetPlatform()
    ext = _GetExtension()

    pesq_path = os.path.join(toolchain_dir, platform, 'pesq' + ext)
    if not os.path.isfile(pesq_path):
        pesq_path = None

    polqa_path = os.path.join(toolchain_dir, platform, 'PolqaOem64' + ext)
    if not os.path.isfile(polqa_path):
        polqa_path = None

    if (platform != 'mac' and not polqa_path) or not pesq_path:
        logging.error(NO_TOOLS_ERROR_MESSAGE, toolchain_dir,
                      os.path.join(tools_dir, 'download_tools.py'),
                      toolchain_dir)

    return pesq_path, polqa_path


def ExtractTestRuns(lines, echo=False):
    """Extracts information about tests from the output of a test runner.

  Produces tuples
  (android_device, test_name, reference_file, degraded_file, cur_perf_results).
  """
    for line in lines:
        if echo:
            sys.stdout.write(line)

        # Output from Android has a prefix with the device name.
        android_prefix_re = r'(?:I\b.+\brun_tests_on_device\((.+?)\)\s*)?'
        test_re = r'^' + android_prefix_re + (r'TEST (\w+) ([^ ]+?) ([^\s]+)'
                                              r' ?([^\s]+)?\s*$')

        match = re.search(test_re, line)
        if match:
            yield match.groups()


def _GetFile(file_path,
             out_dir,
             move=False,
             android=False,
             adb_prefix=('adb', )):
    out_file_name = os.path.basename(file_path)
    out_file_path = os.path.join(out_dir, out_file_name)

    if android:
        # Pull the file from the connected Android device.
        adb_command = adb_prefix + ('pull', file_path, out_dir)
        subprocess.check_call(_LogCommand(adb_command))
        if move:
            # Remove that file.
            adb_command = adb_prefix + ('shell', 'rm', file_path)
            subprocess.check_call(_LogCommand(adb_command))
    elif os.path.abspath(file_path) != os.path.abspath(out_file_path):
        if move:
            shutil.move(file_path, out_file_path)
        else:
            shutil.copy(file_path, out_file_path)

    return out_file_path


def _RunPesq(executable_path,
             reference_file,
             degraded_file,
             sample_rate_hz=16000):
    directory = os.path.dirname(reference_file)
    assert os.path.dirname(degraded_file) == directory

    # Analyze audio.
    command = [
        executable_path,
        '+%d' % sample_rate_hz,
        os.path.basename(reference_file),
        os.path.basename(degraded_file)
    ]
    # Need to provide paths in the current directory due to a bug in PESQ:
    # On Mac, for some 'path/to/file.wav', if 'file.wav' is longer than
    # 'path/to', PESQ crashes.
    out = subprocess.check_output(_LogCommand(command),
                                  cwd=directory,
                                  stderr=subprocess.STDOUT)

    # Find the scores in stdout of PESQ.
    match = re.search(
        r'Prediction \(Raw MOS, MOS-LQO\):\s+=\s+([\d.]+)\s+([\d.]+)', out)
    if match:
        raw_mos, _ = match.groups()

        return {'pesq_mos': (raw_mos, 'unitless')}
    else:
        logging.error('PESQ: %s', out.splitlines()[-1])
        return {}


def _RunPolqa(executable_path, reference_file, degraded_file):
    # Analyze audio.
    command = [
        executable_path, '-q', '-LC', 'NB', '-Ref', reference_file, '-Test',
        degraded_file
    ]
    process = subprocess.Popen(_LogCommand(command),
                               stdout=subprocess.PIPE,
                               stderr=subprocess.PIPE)
    out, err = process.communicate()

    # Find the scores in stdout of POLQA.
    match = re.search(r'\bMOS-LQO:\s+([\d.]+)', out)

    if process.returncode != 0 or not match:
        if process.returncode == 2:
            logging.warning('%s (2)', err.strip())
            logging.warning('POLQA license error, skipping test.')
        else:
            logging.error('%s (%d)', err.strip(), process.returncode)
        return {}

    mos_lqo, = match.groups()
    return {'polqa_mos_lqo': (mos_lqo, 'unitless')}


def _MergeInPerfResultsFromCcTests(histograms, run_perf_results_file):
    from tracing.value import histogram_set

    cc_histograms = histogram_set.HistogramSet()
    with open(run_perf_results_file, 'rb') as f:
        contents = f.read()
        if not contents:
            return

        cc_histograms.ImportProto(contents)

    histograms.Merge(cc_histograms)


Analyzer = collections.namedtuple(
    'Analyzer', ['name', 'func', 'executable', 'sample_rate_hz'])


def _ConfigurePythonPath(args):
    script_dir = os.path.dirname(os.path.realpath(__file__))
    checkout_root = os.path.abspath(
        os.path.join(script_dir, os.pardir, os.pardir))

    # TODO(https://crbug.com/1029452): Use a copy rule and add these from the out
    # dir like for the third_party/protobuf code.
    sys.path.insert(
        0, os.path.join(checkout_root, 'third_party', 'catapult', 'tracing'))

    # The low_bandwidth_audio_perf_test gn rule will build the protobuf stub for
    # python, so put it in the path for this script before we attempt to import
    # it.
    histogram_proto_path = os.path.join(os.path.abspath(args.build_dir),
                                        'pyproto', 'tracing', 'tracing',
                                        'proto')
    sys.path.insert(0, histogram_proto_path)
    proto_stub_path = os.path.join(os.path.abspath(args.build_dir), 'pyproto')
    sys.path.insert(0, proto_stub_path)

    # Fail early in case the proto hasn't been built.
    try:
        import histogram_pb2
    except ImportError as e:
        logging.exception(e)
        raise ImportError(
            'Could not import histogram_pb2. You need to build the '
            'low_bandwidth_audio_perf_test target before invoking '
            'this script. Expected to find '
            'histogram_pb2.py in %s.' % histogram_proto_path)


def main():
    # pylint: disable=W0101
    logging.basicConfig(level=logging.INFO)
    logging.info('Invoked with %s', str(sys.argv))

    args = _ParseArgs()

    _ConfigurePythonPath(args)

    # Import catapult modules here after configuring the pythonpath.
    from tracing.value import histogram_set
    from tracing.value.diagnostics import reserved_infos
    from tracing.value.diagnostics import generic_set

    pesq_path, polqa_path = _GetPathToTools()
    if pesq_path is None:
        return 1

    out_dir = os.path.join(args.build_dir, '..')
    if args.android:
        test_command = [
            os.path.join(args.build_dir, 'bin',
                         'run_low_bandwidth_audio_test'), '-v',
            '--num-retries', args.num_retries
        ]
    else:
        test_command = [
            os.path.join(args.build_dir, 'low_bandwidth_audio_test')
        ]

    analyzers = [Analyzer('pesq', _RunPesq, pesq_path, 16000)]
    # Check if POLQA can run at all, or skip the 48 kHz tests entirely.
    example_path = os.path.join(SRC_DIR, 'resources', 'voice_engine',
                                'audio_tiny48.wav')
    if polqa_path and _RunPolqa(polqa_path, example_path, example_path):
        analyzers.append(Analyzer('polqa', _RunPolqa, polqa_path, 48000))

    histograms = histogram_set.HistogramSet()
    for analyzer in analyzers:
        # Start the test executable that produces audio files.
        test_process = subprocess.Popen(_LogCommand(test_command + [
            '--sample_rate_hz=%d' % analyzer.sample_rate_hz,
            '--test_case_prefix=%s' % analyzer.name,
        ] + args.extra_test_args),
                                        stdout=subprocess.PIPE,
                                        stderr=subprocess.STDOUT)
        perf_results_file = None
        try:
            lines = iter(test_process.stdout.readline, '')
            for result in ExtractTestRuns(lines, echo=True):
                (android_device, test_name, reference_file, degraded_file,
                 perf_results_file) = result

                adb_prefix = (args.adb_path, )
                if android_device:
                    adb_prefix += ('-s', android_device)

                reference_file = _GetFile(reference_file,
                                          out_dir,
                                          android=args.android,
                                          adb_prefix=adb_prefix)
                degraded_file = _GetFile(degraded_file,
                                         out_dir,
                                         move=True,
                                         android=args.android,
                                         adb_prefix=adb_prefix)

                analyzer_results = analyzer.func(analyzer.executable,
                                                 reference_file, degraded_file)
                for metric, (value, units) in analyzer_results.items():
                    hist = histograms.CreateHistogram(metric, units, [value])
                    user_story = generic_set.GenericSet([test_name])
                    hist.diagnostics[reserved_infos.STORIES.name] = user_story

                    # Output human readable results.
                    print 'RESULT %s: %s= %s %s' % (metric, test_name, value,
                                                    units)

                if args.remove:
                    os.remove(reference_file)
                    os.remove(degraded_file)
        finally:
            test_process.terminate()
        if perf_results_file:
            perf_results_file = _GetFile(perf_results_file,
                                         out_dir,
                                         move=True,
                                         android=args.android,
                                         adb_prefix=adb_prefix)
            _MergeInPerfResultsFromCcTests(histograms, perf_results_file)
            if args.remove:
                os.remove(perf_results_file)

    if args.isolated_script_test_perf_output:
        with open(args.isolated_script_test_perf_output, 'wb') as f:
            f.write(histograms.AsProto().SerializeToString())

    return test_process.wait()


if __name__ == '__main__':
    sys.exit(main())
