# 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 simulation 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
import pydub

from . import audioproc_wrapper
from . import eval_scores_factory
from . import evaluation
from . import external_vad
from . import signal_processing
from . import simulation
from . import test_data_generation_factory


class TestApmModuleSimulator(unittest.TestCase):
  """Unit tests for the ApmModuleSimulator class.
  """

  def setUp(self):
    """Create temporary folders and fake audio track."""
    self._output_path = tempfile.mkdtemp()
    self._tmp_path = tempfile.mkdtemp()

    silence = pydub.AudioSegment.silent(duration=1000, frame_rate=48000)
    fake_signal = signal_processing.SignalProcessingUtils.GenerateWhiteNoise(
        silence)
    self._fake_audio_track_path = os.path.join(self._output_path, 'fake.wav')
    signal_processing.SignalProcessingUtils.SaveWav(
        self._fake_audio_track_path, fake_signal)

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

  def testSimulation(self):
    # Instance dependencies to mock and inject.
    ap_wrapper = audioproc_wrapper.AudioProcWrapper(
        audioproc_wrapper.AudioProcWrapper.DEFAULT_APM_SIMULATOR_BIN_PATH)
    evaluator = evaluation.ApmModuleEvaluator()
    ap_wrapper.Run = mock.MagicMock(name='Run')
    evaluator.Run = mock.MagicMock(name='Run')

    # Instance non-mocked dependencies.
    test_data_generator_factory = (
        test_data_generation_factory.TestDataGeneratorFactory(
            aechen_ir_database_path='',
            noise_tracks_path='',
            copy_with_identity=False))
    evaluation_score_factory = eval_scores_factory.EvaluationScoreWorkerFactory(
        polqa_tool_bin_path=os.path.join(
            os.path.dirname(__file__), 'fake_polqa'))

    # Instance simulator.
    simulator = simulation.ApmModuleSimulator(
        test_data_generator_factory=test_data_generator_factory,
        evaluation_score_factory=evaluation_score_factory,
        ap_wrapper=ap_wrapper,
        evaluator=evaluator,
        external_vads={'fake': external_vad.ExternalVad(os.path.join(
            os.path.dirname(__file__), 'fake_external_vad.py'), 'fake')}
    )

    # What to simulate.
    config_files = ['apm_configs/default.json']
    input_files = [self._fake_audio_track_path]
    test_data_generators = ['identity', 'white_noise']
    eval_scores = ['audio_level_mean', 'polqa']

    # Run all simulations.
    simulator.Run(
        config_filepaths=config_files,
        capture_input_filepaths=input_files,
        test_data_generator_names=test_data_generators,
        eval_score_names=eval_scores,
        output_dir=self._output_path)

    # Check.
    # TODO(alessiob): Once the TestDataGenerator classes can be configured by
    # the client code (e.g., number of SNR pairs for the white noise test data
    # generator), the exact number of calls to ap_wrapper.Run and evaluator.Run
    # is known; use that with assertEqual.
    min_number_of_simulations = len(config_files) * len(input_files) * len(
        test_data_generators)
    self.assertGreaterEqual(len(ap_wrapper.Run.call_args_list),
                            min_number_of_simulations)
    self.assertGreaterEqual(len(evaluator.Run.call_args_list),
                            min_number_of_simulations)

  def testInputSignalCreation(self):
    # Instance simulator.
    simulator = simulation.ApmModuleSimulator(
        test_data_generator_factory=(
            test_data_generation_factory.TestDataGeneratorFactory(
                aechen_ir_database_path='',
                noise_tracks_path='',
                copy_with_identity=False)),
        evaluation_score_factory=(
            eval_scores_factory.EvaluationScoreWorkerFactory(
                polqa_tool_bin_path=os.path.join(
                    os.path.dirname(__file__), 'fake_polqa'))),
        ap_wrapper=audioproc_wrapper.AudioProcWrapper(
            audioproc_wrapper.AudioProcWrapper.DEFAULT_APM_SIMULATOR_BIN_PATH),
        evaluator=evaluation.ApmModuleEvaluator())

    # Inexistent input files to be silently created.
    input_files = [
        os.path.join(self._tmp_path, 'pure_tone-440_1000.wav'),
        os.path.join(self._tmp_path, 'pure_tone-1000_500.wav'),
    ]
    self.assertFalse(any([os.path.exists(input_file) for input_file in (
        input_files)]))

    # The input files are created during the simulation.
    simulator.Run(
        config_filepaths=['apm_configs/default.json'],
        capture_input_filepaths=input_files,
        test_data_generator_names=['identity'],
        eval_score_names=['audio_level_peak'],
        output_dir=self._output_path)
    self.assertTrue(all([os.path.exists(input_file) for input_file in (
        input_files)]))

  def testPureToneGenerationWithTotalHarmonicDistorsion(self):
    logging.warning = mock.MagicMock(name='warning')

    # Instance simulator.
    simulator = simulation.ApmModuleSimulator(
        test_data_generator_factory=(
            test_data_generation_factory.TestDataGeneratorFactory(
                aechen_ir_database_path='',
                noise_tracks_path='',
                copy_with_identity=False)),
        evaluation_score_factory=(
            eval_scores_factory.EvaluationScoreWorkerFactory(
                polqa_tool_bin_path=os.path.join(
                    os.path.dirname(__file__), 'fake_polqa'))),
        ap_wrapper=audioproc_wrapper.AudioProcWrapper(
            audioproc_wrapper.AudioProcWrapper.DEFAULT_APM_SIMULATOR_BIN_PATH),
        evaluator=evaluation.ApmModuleEvaluator())

    # What to simulate.
    config_files = ['apm_configs/default.json']
    input_files = [os.path.join(self._tmp_path, 'pure_tone-440_1000.wav')]
    eval_scores = ['thd']

    # Should work.
    simulator.Run(
        config_filepaths=config_files,
        capture_input_filepaths=input_files,
        test_data_generator_names=['identity'],
        eval_score_names=eval_scores,
        output_dir=self._output_path)
    self.assertFalse(logging.warning.called)

    # Warning expected.
    simulator.Run(
        config_filepaths=config_files,
        capture_input_filepaths=input_files,
        test_data_generator_names=['white_noise'],  # Not allowed with THD.
        eval_score_names=eval_scores,
        output_dir=self._output_path)
    logging.warning.assert_called_with('the evaluation failed: %s', (
        'The THD score cannot be used with any test data generator other than '
        '"identity"'))

  #   # Init.
  #   generator = test_data_generation.IdentityTestDataGenerator('tmp')
  #   input_signal_filepath = os.path.join(
  #       self._test_data_cache_path, 'pure_tone-440_1000.wav')

  #   # Check that the input signal is generated.
  #   self.assertFalse(os.path.exists(input_signal_filepath))
  #   generator.Generate(
  #       input_signal_filepath=input_signal_filepath,
  #       test_data_cache_path=self._test_data_cache_path,
  #       base_output_path=self._base_output_path)
  #   self.assertTrue(os.path.exists(input_signal_filepath))

  #   # Check input signal properties.
  #   input_signal = signal_processing.SignalProcessingUtils.LoadWav(
  #       input_signal_filepath)
  #   self.assertEqual(1000, len(input_signal))
