"""Common utilities for Brotli tests."""

from __future__ import print_function
import filecmp
import glob
import itertools
import os
import sys
import sysconfig
import tempfile
import unittest

# TODO(eustas): use str(pathlib.PurePath(file).parent.parent) for Python 3.4+
project_dir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
test_dir = os.getenv('BROTLI_TESTS_PATH')
BRO_ARGS = [os.getenv('BROTLI_WRAPPER')]

# Fallbacks
if test_dir is None:
  test_dir = os.path.join(project_dir, 'tests')
if BRO_ARGS[0] is None:
  python_exe = sys.executable or 'python'
  bro_path = os.path.join(project_dir, 'python', 'bro.py')
  BRO_ARGS = [python_exe, bro_path]

# Get the platform/version-specific build folder.
# By default, the distutils build base is in the same location as setup.py.
platform_lib_name = 'lib.{platform}-{version[0]}.{version[1]}'.format(
    platform=sysconfig.get_platform(), version=sys.version_info
)
build_dir = os.path.join(project_dir, 'bin', platform_lib_name)

# Prepend the build folder to sys.path and the PYTHONPATH environment variable.
if build_dir not in sys.path:
  sys.path.insert(0, build_dir)
TEST_ENV = dict(os.environ)
if 'PYTHONPATH' not in TEST_ENV:
  TEST_ENV['PYTHONPATH'] = build_dir
else:
  TEST_ENV['PYTHONPATH'] = build_dir + os.pathsep + TEST_ENV['PYTHONPATH']

TESTDATA_DIR = os.path.join(test_dir, 'testdata')

TESTDATA_FILES = [
    'empty',  # Empty file
    '10x10y',  # Small text
    'alice29.txt',  # Large text
    'random_org_10k.bin',  # Small data
    'mapsdatazrh',  # Large data
    'ukkonooa',  # Poem
    'cp1251-utf16le',  # Codepage 1251 table saved in UTF16-LE encoding
    'cp852-utf8',  # Codepage 852 table saved in UTF8 encoding
    # TODO(eustas): add test on already compressed content
]

# Some files might be missing in a lightweight sources pack.
TESTDATA_PATH_CANDIDATES = [
    os.path.join(TESTDATA_DIR, f) for f in TESTDATA_FILES
]

TESTDATA_PATHS = [
    path for path in TESTDATA_PATH_CANDIDATES if os.path.isfile(path)
]

TESTDATA_PATHS_FOR_DECOMPRESSION = glob.glob(
    os.path.join(TESTDATA_DIR, '*.compressed')
)

TEMP_DIR = tempfile.mkdtemp()


def get_temp_compressed_name(filename):
  return os.path.join(TEMP_DIR, os.path.basename(filename + '.bro'))


def get_temp_uncompressed_name(filename):
  return os.path.join(TEMP_DIR, os.path.basename(filename + '.unbro'))


def bind_method_args(method, *args, **kwargs):
  return lambda self: method(self, *args, **kwargs)


# TODO(eustas): migrate to absl.testing.parameterized.
def generate_test_methods(
    test_case_class, for_decompression=False, variants=None
):
  """Adds test methods for each test data file and each variant.

  This makes identifying problems with specific compression scenarios easier.

  Args:
    test_case_class: The test class to add methods to.
    for_decompression: If True, uses compressed test data files.
    variants: A dictionary where keys are option names and values are lists of
      possible values for that option. Each combination of variants will
      generate a separate test method.
  """
  if for_decompression:
    paths = TESTDATA_PATHS_FOR_DECOMPRESSION
  else:
    paths = TESTDATA_PATHS
  opts = []
  if variants:
    opts_list = []
    for k, v in variants.items():
      opts_list.append([r for r in itertools.product([k], v)])
    for o in itertools.product(*opts_list):
      opts_name = '_'.join([str(i) for i in itertools.chain(*o)])
      opts_dict = dict(o)
      opts.append([opts_name, opts_dict])
  else:
    opts.append(['', {}])
  for method in [m for m in dir(test_case_class) if m.startswith('_test')]:
    for testdata in paths:
      for opts_name, opts_dict in opts:
        f = os.path.splitext(os.path.basename(testdata))[0]
        name = 'test_{method}_{options}_{file}'.format(
            method=method, options=opts_name, file=f
        )
        func = bind_method_args(
            getattr(test_case_class, method), testdata, **opts_dict
        )
        setattr(test_case_class, name, func)


class TestCase(unittest.TestCase):
  """Base class for Brotli test cases.

  Provides common setup and teardown logic, including cleaning up temporary
  files and a utility for comparing file contents.
  """

  def tearDown(self):
    for f in TESTDATA_PATHS:
      try:
        os.unlink(get_temp_compressed_name(f))
      except OSError:
        pass
      try:
        os.unlink(get_temp_uncompressed_name(f))
      except OSError:
        pass
    super().tearDown()

  def assert_files_match(self, first, second):
    self.assertTrue(
        filecmp.cmp(first, second, shallow=False),
        'File {} differs from {}'.format(first, second),
    )
