#!/usr/bin/env python3
"""Meant to be run from inside python-test-runner container,
where this track repo is mounted at /python
"""
import argparse
from functools import wraps
from itertools import zip_longest
import json
from pathlib import Path
import shutil
import subprocess
import sys
import tempfile
from typing import List
from data import Config, ExerciseConfig, ExerciseInfo, ExerciseStatus

# Allow high-performance tests to be skipped
ALLOW_SKIP = ['alphametics', 'largest-series-product']

TEST_RUNNER_DIR = Path('/opt/test-runner')

RUNNERS = {}


def runner(name):
    def _decorator(runner_func):
        RUNNERS[name] = runner_func
        @wraps(runner_func)
        def _wrapper(exercise: ExerciseInfo, workdir: Path, quiet: bool = False):
            return runner_func(exercise, workdir, quiet=quiet)
        return _wrapper
    return _decorator


def copy_file(src: Path, dst: Path, strip_skips=False):
    if strip_skips:
        with src.open('r') as src_file:
            lines = [line for line in src_file.readlines()
                        if not line.strip().startswith('@unittest.skip')]
        with dst.open('w') as dst_file:
            dst_file.writelines(lines)
    else:
        shutil.copy2(src, dst)

def copy_solution_files(exercise: ExerciseInfo, workdir: Path, exercise_config: ExerciseConfig = None):
    if exercise_config is not None:
        solution_files = exercise_config.files.solution
        exemplar_files = exercise_config.files.exemplar
        helper_files = exercise_config.files.editor
    else:
        solution_files = []
        exemplar_files = []
        helper_files = []

    if helper_files:
        helper_files = [exercise.path / h for h in helper_files]
        for helper_file in helper_files:
            dst = workdir / helper_file.relative_to(exercise.path)
            copy_file(helper_file, dst)

    if not solution_files:
        solution_files.append(exercise.solution_stub.name)
    solution_files = [exercise.path / s for s in solution_files]
    if not exemplar_files:
        exemplar_files.append(exercise.exemplar_file.relative_to(exercise.path))
    exemplar_files = [exercise.path / e for e in exemplar_files]

    for solution_file, exemplar_file in zip_longest(solution_files, exemplar_files):
        if solution_file is None:
            copy_file(exemplar_file, workdir / exemplar_file.name)
        elif exemplar_file is None:
            copy_file(solution_file, workdir / solution_file.name)
        else:
            dst = workdir / solution_file.relative_to(exercise.path)
            copy_file(exemplar_file, dst)


def copy_test_files(exercise: ExerciseInfo, workdir: Path, exercise_config = None):
    if exercise_config is not None:
        test_files = exercise_config.files.test
        helper_files = exercise_config.files.editor
    else:
        test_files = []
        helper_files = []

    if helper_files:
        for helper_file_name in helper_files:
            helper_file = exercise.path / helper_file_name
            helper_file_out = workdir / helper_file_name
            copy_file(helper_file, helper_file_out, strip_skips=(exercise.slug not in ALLOW_SKIP))

    if not test_files:
        test_files.append(exercise.test_file.name)

    for test_file_name in test_files:
        test_file = exercise.path / test_file_name
        test_file_out = workdir / test_file_name
        copy_file(test_file, test_file_out, strip_skips=(exercise.slug not in ALLOW_SKIP))


def copy_exercise_files(exercise: ExerciseInfo, workdir: Path):
    exercise_config = None
    if exercise.config_file.is_file():
        workdir_meta = workdir / '.meta'
        workdir_meta.mkdir(exist_ok=True)
        copy_file(exercise.config_file, workdir_meta / exercise.config_file.name)
        exercise_config = exercise.load_config()
    copy_solution_files(exercise, workdir, exercise_config)