package com.atlassian.bitbucket.test.runners;

import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.manipulation.Filter;
import org.junit.runner.manipulation.Filterable;
import org.junit.runner.manipulation.NoTestsRemainException;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Parameterized;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.TestClass;

import static org.junit.runners.Parameterized.*;

/**
 * A base delegating {@link Runner} that supports {@link Parameter @Parameter} fields and
 * {@link Parameters @Parameters} methods in the same way the {@link Parameterized} class does.
 */
public abstract class ParameterisedRunnerBase extends Runner implements Filterable {
    protected final TestClass testClass;
    protected final ParentRunner<?> target;

    public ParameterisedRunnerBase(Class<?> klass) throws Throwable {
        testClass = new TestClass(klass);

        if (isParameterised()) {
            target = new Parameterized(klass);
        } else {
            target = new BlockJUnit4ClassRunner(klass);
        }
    }

    boolean isParameterised() {
        return !testClass.getAnnotatedMethods(Parameters.class).isEmpty();
    }

    @Override
    public Description getDescription() {
        return target.getDescription();
    }

    @Override
    public void run(RunNotifier notifier) {
        target.run(notifier);
    }

    public void filter(Filter filter) throws NoTestsRemainException {
        filter.apply(target);
    }

    protected TestClass getTestClass() {
        return testClass;
    }
}
