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

"""Imports a filtered subset of the scores and configurations computed
by apm_quality_assessment.py into a pandas data frame.
"""

import argparse
import glob
import logging
import os
import re
import sys

try:
  import pandas as pd
except ImportError:
  logging.critical('Cannot import the third-party Python package pandas')
  sys.exit(1)

from . import data_access as data_access
from . import simulation as sim

# Compiled regular expressions used to extract score descriptors.
RE_CONFIG_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixApmConfig() + r'(.+)')
RE_CAPTURE_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixCapture() + r'(.+)')
RE_RENDER_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixRender() + r'(.+)')
RE_ECHO_SIM_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixEchoSimulator() + r'(.+)')
RE_TEST_DATA_GEN_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixTestDataGenerator() + r'(.+)')
RE_TEST_DATA_GEN_PARAMS = re.compile(
    sim.ApmModuleSimulator.GetPrefixTestDataGeneratorParameters() + r'(.+)')
RE_SCORE_NAME = re.compile(
    sim.ApmModuleSimulator.GetPrefixScore() + r'(.+)(\..+)')

def InstanceArgumentsParser():
  """Arguments parser factory.
  """
  parser = argparse.ArgumentParser(description=(
      'Override this description in a user script by changing'
      ' `parser.description` of the returned parser.'))

  parser.add_argument('-o', '--output_dir', required=True,
                      help=('the same base path used with the '
                            'apm_quality_assessment tool'))

  parser.add_argument('-f', '--filename_suffix',
                      help=('suffix of the exported file'))

  parser.add_argument('-c', '--config_names', type=re.compile,
                      help=('regular expression to filter the APM configuration'
                            ' names'))

  parser.add_argument('-i', '--capture_names', type=re.compile,
                      help=('regular expression to filter the capture signal '
                            'names'))

  parser.add_argument('-r', '--render_names', type=re.compile,
                      help=('regular expression to filter the render signal '
                            'names'))

  parser.add_argument('-e', '--echo_simulator_names', type=re.compile,
                      help=('regular expression to filter the echo simulator '
                            'names'))

  parser.add_argument('-t', '--test_data_generators', type=re.compile,
                      help=('regular expression to filter the test data '
                            'generator names'))

  parser.add_argument('-s', '--eval_scores', type=re.compile,
                      help=('regular expression to filter the evaluation score '
                            'names'))

  return parser


def _GetScoreDescriptors(score_filepath):
  """Extracts a score descriptor from the given score file path.

  Args:
    score_filepath: path to the score file.

  Returns:
    A tuple of strings (APM configuration name, capture audio track name,
    render audio track name, echo simulator name, test data generator name,
    test data generator parameters as string, evaluation score name).
  """
  fields = score_filepath.split(os.sep)[-7:]
  extract_name = lambda index, reg_expr: (
      reg_expr.match(fields[index]).groups(0)[0])
  return (
      extract_name(0, RE_CONFIG_NAME),
      extract_name(1, RE_CAPTURE_NAME),
      extract_name(2, RE_RENDER_NAME),
      extract_name(3, RE_ECHO_SIM_NAME),
      extract_name(4, RE_TEST_DATA_GEN_NAME),
      extract_name(5, RE_TEST_DATA_GEN_PARAMS),
      extract_name(6, RE_SCORE_NAME),
  )


def _ExcludeScore(config_name, capture_name, render_name, echo_simulator_name,
                  test_data_gen_name, score_name, args):
  """Decides whether excluding a score.

  A set of optional regular expressions in args is used to determine if the
  score should be excluded (depending on its |*_name| descriptors).

  Args:
    config_name: APM configuration name.
    capture_name: capture audio track name.
    render_name: render audio track name.
    echo_simulator_name: echo simulator name.
    test_data_gen_name: test data generator name.
    score_name: evaluation score name.
    args: parsed arguments.

  Returns:
    A boolean.
  """
  value_regexpr_pairs = [
      (config_name, args.config_names),
      (capture_name, args.capture_names),
      (render_name, args.render_names),
      (echo_simulator_name, args.echo_simulator_names),
      (test_data_gen_name, args.test_data_generators),
      (score_name, args.eval_scores),
  ]

  # Score accepted if each value matches the corresponding regular expression.
  for value, regexpr in value_regexpr_pairs:
    if regexpr is None:
      continue
    if not regexpr.match(value):
      return True

  return False


def FindScores(src_path, args):
  """Given a search path, find scores and return a DataFrame object.

  Args:
    src_path: Search path pattern.
    args: parsed arguments.

  Returns:
    A DataFrame object.
  """
  # Get scores.
  scores = []
  for score_filepath in glob.iglob(src_path):
    # Extract score descriptor fields from the path.
    (config_name,
     capture_name,
     render_name,
     echo_simulator_name,
     test_data_gen_name,
     test_data_gen_params,
     score_name) = _GetScoreDescriptors(score_filepath)

    # Ignore the score if required.
    if _ExcludeScore(
        config_name,
        capture_name,
        render_name,
        echo_simulator_name,
        test_data_gen_name,
        score_name,
        args):
      logging.info(
          'ignored score: %s %s %s %s %s %s',
          config_name,
          capture_name,
          render_name,
          echo_simulator_name,
          test_data_gen_name,
          score_name)
      continue

    # Read metadata and score.
    metadata = data_access.Metadata.LoadAudioTestDataPaths(
        os.path.split(score_filepath)[0])
    score = data_access.ScoreFile.Load(score_filepath)

    # Add a score with its descriptor fields.
    scores.append((
        metadata['clean_capture_input_filepath'],
        metadata['echo_free_capture_filepath'],
        metadata['echo_filepath'],
        metadata['render_filepath'],
        metadata['capture_filepath'],
        metadata['apm_output_filepath'],
        metadata['apm_reference_filepath'],
        config_name,
        capture_name,
        render_name,
        echo_simulator_name,
        test_data_gen_name,
        test_data_gen_params,
        score_name,
        score,
    ))

  return pd.DataFrame(
      data=scores,
      columns=(
          'clean_capture_input_filepath',
          'echo_free_capture_filepath',
          'echo_filepath',
          'render_filepath',
          'capture_filepath',
          'apm_output_filepath',
          'apm_reference_filepath',
          'apm_config',
          'capture',
          'render',
          'echo_simulator',
          'test_data_gen',
          'test_data_gen_params',
          'eval_score_name',
          'score',
      ))


def ConstructSrcPath(args):
  return os.path.join(
      args.output_dir,
      sim.ApmModuleSimulator.GetPrefixApmConfig() + '*',
      sim.ApmModuleSimulator.GetPrefixCapture() + '*',
      sim.ApmModuleSimulator.GetPrefixRender() + '*',
      sim.ApmModuleSimulator.GetPrefixEchoSimulator() + '*',
      sim.ApmModuleSimulator.GetPrefixTestDataGenerator() + '*',
      sim.ApmModuleSimulator.GetPrefixTestDataGeneratorParameters() + '*',
      sim.ApmModuleSimulator.GetPrefixScore() + '*')
