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

"""Unit tests for the input mixer module.
"""

import logging
import os
import shutil
import sys
import tempfile
import unittest

SRC = os.path.abspath(os.path.join(
    os.path.dirname((__file__)), os.pardir, os.pardir, os.pardir, os.pardir))
sys.path.append(os.path.join(SRC, 'third_party', 'pymock'))

import mock

from . import exceptions
from . import input_mixer
from . import signal_processing


class TestApmInputMixer(unittest.TestCase):
  """Unit tests for the ApmInputMixer class.
  """

  # Audio track file names created in setUp().
  _FILENAMES = ['capture', 'echo_1', 'echo_2', 'shorter', 'longer']

  # Target peak power level (dBFS) of each audio track file created in setUp().
  # These values are hand-crafted in order to make saturation happen when
  # capture and echo_2 are mixed and the contrary for capture and echo_1.
  # None means that the power is not changed.
  _MAX_PEAK_POWER_LEVELS = [-10.0, -5.0, 0.0, None, None]

  # Audio track file durations in milliseconds.
  _DURATIONS = [1000, 1000, 1000, 800, 1200]

  _SAMPLE_RATE = 48000

  def setUp(self):
    """Creates temporary data."""
    self._tmp_path = tempfile.mkdtemp()

    # Create audio track files.
    self._audio_tracks = {}
    for filename, peak_power, duration in zip(
        self._FILENAMES, self._MAX_PEAK_POWER_LEVELS, self._DURATIONS):
      audio_track_filepath = os.path.join(self._tmp_path, '{}.wav'.format(
          filename))

      # Create a pure tone with the target peak power level.
      template = signal_processing.SignalProcessingUtils.GenerateSilence(
          duration=duration, sample_rate=self._SAMPLE_RATE)
      signal = signal_processing.SignalProcessingUtils.GeneratePureTone(
          template)
      if peak_power is not None:
        signal = signal.apply_gain(-signal.max_dBFS + peak_power)

      signal_processing.SignalProcessingUtils.SaveWav(
        audio_track_filepath, signal)
      self._audio_tracks[filename] = {
          'filepath': audio_track_filepath,
          'num_samples': signal_processing.SignalProcessingUtils.CountSamples(
              signal)
      }

  def tearDown(self):
    """Recursively deletes temporary folders."""
    shutil.rmtree(self._tmp_path)

  def testCheckMixSameDuration(self):
    """Checks the duration when mixing capture and echo with same duration."""
    mix_filepath = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['echo_1']['filepath'])
    self.assertTrue(os.path.exists(mix_filepath))

    mix = signal_processing.SignalProcessingUtils.LoadWav(mix_filepath)
    self.assertEqual(self._audio_tracks['capture']['num_samples'],
                     signal_processing.SignalProcessingUtils.CountSamples(mix))

  def testRejectShorterEcho(self):
    """Rejects echo signals that are shorter than the capture signal."""
    try:
      _ = input_mixer.ApmInputMixer.Mix(
          self._tmp_path,
          self._audio_tracks['capture']['filepath'],
          self._audio_tracks['shorter']['filepath'])
      self.fail('no exception raised')
    except exceptions.InputMixerException:
      pass

  def testCheckMixDurationWithLongerEcho(self):
    """Checks the duration when mixing an echo longer than the capture."""
    mix_filepath = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['longer']['filepath'])
    self.assertTrue(os.path.exists(mix_filepath))

    mix = signal_processing.SignalProcessingUtils.LoadWav(mix_filepath)
    self.assertEqual(self._audio_tracks['capture']['num_samples'],
                     signal_processing.SignalProcessingUtils.CountSamples(mix))

  def testCheckOutputFileNamesConflict(self):
    """Checks that different echo files lead to different output file names."""
    mix1_filepath = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['echo_1']['filepath'])
    self.assertTrue(os.path.exists(mix1_filepath))

    mix2_filepath = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['echo_2']['filepath'])
    self.assertTrue(os.path.exists(mix2_filepath))

    self.assertNotEqual(mix1_filepath, mix2_filepath)

  def testHardClippingLogExpected(self):
    """Checks that hard clipping warning is raised when occurring."""
    logging.warning = mock.MagicMock(name='warning')
    _ = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['echo_2']['filepath'])
    logging.warning.assert_called_once_with(
        input_mixer.ApmInputMixer.HardClippingLogMessage())

  def testHardClippingLogNotExpected(self):
    """Checks that hard clipping warning is not raised when not occurring."""
    logging.warning = mock.MagicMock(name='warning')
    _ = input_mixer.ApmInputMixer.Mix(
        self._tmp_path,
        self._audio_tracks['capture']['filepath'],
        self._audio_tracks['echo_1']['filepath'])
    self.assertNotIn(
        mock.call(input_mixer.ApmInputMixer.HardClippingLogMessage()),
        logging.warning.call_args_list)
