"""
Checks that files duplicated across schemes/implementations are consistent.
"""

import difflib
import os
import sys

import yaml

import helpers
import pqclean

sys.tracebacklimit = 0


def pytest_generate_tests(metafunc):
    ids = []
    argvalues = []
    if 'duplicate_consistency' not in os.environ.get('PQCLEAN_SKIP_TESTS', '').split(','):
        for scheme in pqclean.Scheme.all_schemes():
            for implementation in scheme.implementations:
                if os.path.isfile(
                        os.path.join(
                            'duplicate_consistency',
                            '{}_{}.yml'.format(scheme.name, implementation.name))):
                    metafile = os.path.join(
                        'duplicate_consistency',
                        '{}_{}.yml'.format(scheme.name, implementation.name))
                    with open(metafile, encoding='utf-8') as f:
                        metadata = yaml.safe_load(f.read())
                        for group in metadata['consistency_checks']:
                            source = pqclean.Implementation.by_name(
                                group['source']['scheme'],
                                group['source']['implementation'])
                            argvalues.append(
                                (implementation, source, group['files']))
                            ids.append(
                                "{metafile}: {scheme.name} {implementation.name}"
                                .format(scheme=scheme,
                                        implementation=implementation,
                                        metafile=metafile))
    else:
        # Placeholders so we don't crash
        ids = ['dummy']
        argvalues = [('dummy', 'dummy', 'dummy')]

    metafunc.parametrize(('implementation', 'source', 'files'),
                         argvalues,
                         ids=ids)


def file_get_contents(filename):
    with open(filename) as file:
        return file.read()


@helpers.filtered_test
def test_duplicate_consistency(implementation, source, files):
    """Test sets of files to be identical modulo namespacing"""
    messages = []
    for file in files:
        target_path = os.path.join(source.path(), file)
        this_path = os.path.join(implementation.path(), file)
        target_src = file_get_contents(target_path)\
                        .replace(source.namespace_prefix(), '')\
                        .replace(' ', '')
        this_src = file_get_contents(this_path)\
                        .replace(implementation.namespace_prefix(), '')\
                        .replace(' ', '')

        if not this_src == target_src:
            diff = difflib.unified_diff(
                this_src.splitlines(keepends=True),
                target_src.splitlines(keepends=True),
                fromfile=this_path,
                tofile=target_path)
            messages.append("{} differed:\n{}".format(file, ''.join(diff)))
    if messages:
        raise AssertionError("Files differed:\n{}".format('\n'.join(messages)))


if __name__ == '__main__':
    import pytest
    pytest.main(sys.argv)
