package org.junit.runner;

import java.io.Serializable;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A <code>Description</code> describes a test which is to be run or has been run. <code>Descriptions</code>
 * can be atomic (a single test) or compound (containing children tests). <code>Descriptions</code> are used
 * to provide feedback about the tests that are about to run (for example, the tree view
 * visible in many IDEs) or tests that have been run (for example, the failures view).
 * <p>
 * <code>Descriptions</code> are implemented as a single class rather than a Composite because
 * they are entirely informational. They contain no logic aside from counting their tests.
 * <p>
 * In the past, we used the raw {@link junit.framework.TestCase}s and {@link junit.framework.TestSuite}s
 * to display the tree of tests. This was no longer viable in JUnit 4 because atomic tests no longer have
 * a superclass below {@link Object}. We needed a way to pass a class and name together. Description
 * emerged from this.
 *
 * @see org.junit.runner.Request
 * @see org.junit.runner.Runner
 * @since 4.0
 */
public class Description implements Serializable {
    private static final long serialVersionUID = 1L;

    private static final Pattern METHOD_AND_CLASS_NAME_PATTERN = Pattern
            .compile("([\\s\\S]*)\\((.*)\\)");

    /**
     * Create a <code>Description</code> named <code>name</code>.
     * Generally, you will add children to this <code>Description</code>.
     *
     * @param name the name of the <code>Description</code>
     * @param annotations meta-data about the test, for downstream interpreters
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createSuiteDescription(String name, Annotation... annotations) {
        return new Description(null, name, annotations);
    }

    /**
     * Create a <code>Description</code> named <code>name</code>.
     * Generally, you will add children to this <code>Description</code>.
     *
     * @param name the name of the <code>Description</code>
     * @param uniqueId an arbitrary object used to define uniqueness (in {@link #equals(Object)}
     * @param annotations meta-data about the test, for downstream interpreters
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createSuiteDescription(String name, Serializable uniqueId, Annotation... annotations) {
        return new Description(null, name, uniqueId, annotations);
    }

    /**
     * Create a <code>Description</code> of a single test named <code>name</code> in the 'class' named
     * <code>className</code>. Generally, this will be a leaf <code>Description</code>. This method is a better choice
     * than {@link #createTestDescription(Class, String, Annotation...)} for test runners whose test cases are not
     * defined in an actual Java <code>Class</code>.
     *
     * @param className the class name of the test
     * @param name the name of the test (a method name for test annotated with {@link org.junit.Test})
     * @param annotations meta-data about the test, for downstream interpreters
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createTestDescription(String className, String name, Annotation... annotations) {
        return new Description(null, formatDisplayName(name, className), annotations);
    }

    /**
     * Create a <code>Description</code> of a single test named <code>name</code> in the class <code>clazz</code>.
     * Generally, this will be a leaf <code>Description</code>.
     *
     * @param clazz the class of the test
     * @param name the name of the test (a method name for test annotated with {@link org.junit.Test})
     * @param annotations meta-data about the test, for downstream interpreters
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createTestDescription(Class<?> clazz, String name, Annotation... annotations) {
        return new Description(clazz, formatDisplayName(name, clazz.getName()), annotations);
    }

    /**
     * Create a <code>Description</code> of a single test named <code>name</code> in the class <code>clazz</code>.
     * Generally, this will be a leaf <code>Description</code>.
     * (This remains for binary compatibility with clients of JUnit 4.3)
     *
     * @param clazz the class of the test
     * @param name the name of the test (a method name for test annotated with {@link org.junit.Test})
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createTestDescription(Class<?> clazz, String name) {
        return new Description(clazz, formatDisplayName(name, clazz.getName()));
    }

    /**
     * Create a <code>Description</code> of a single test named <code>name</code> in the class <code>clazz</code>.
     * Generally, this will be a leaf <code>Description</code>.
     *
     * @param name the name of the test (a method name for test annotated with {@link org.junit.Test})
     * @return a <code>Description</code> named <code>name</code>
     */
    public static Description createTestDescription(String className, String name, Serializable uniqueId) {
        return new Description(null, formatDisplayName(name, className), uniqueId);
    }

    private static String formatDisplayName(String name, String className) {
        return String.format("%s(%s)", name, className);
    }

    /**
     * Create a <code>Description</code> named after <code>testClass</code>
     *
     * @param testClass A {@link Class} containing tests
     * @return a <code>Description</code> of <code>testClass</code>
     */
    public static Description createSuiteDescription(Class<?> testClass) {
        return new Description(testClass, testClass.getName(), testClass.getAnnotations());
    }

    /**
     * Create a <code>Description</code> named after <code>testClass</code>
     *
     * @param testClass A not null {@link Class} containing tests
     * @param annotations meta-data about the test, for downstream interpreters
     * @return a <code>Description</code> of <code>testClass</code>
     */
    public static Description createSuiteDescription(Class<?> testClass, Annotation... annotations) {
        return new Description(testClass, testClass.getName(), annotations);
    }

    /**
     * Describes a Runner which runs no tests
     */
    public static final Description EMPTY = new Description(null, "No Tests");

    /**
     * Describes a step in the test-running mechanism that goes so wrong no
     * other description can be used (for example, an exception thrown from a Runner's
     * constructor
     */
    public static final Description TEST_MECHANISM = new Description(null, "Test mechanism");

    /*
     * We have to use the f prefix until the next major release to ensure
     * serialization compatibility. 
     * See https://github.com/junit-team/junit4/issues/976
     */
    private final Collection<Description> fChildren = new ConcurrentLinkedQueue<Description>();
    private final String fDisplayName;
    private final Serializable fUniqueId;
    private final Annotation[] fAnnotations;
    private volatile /* write-once */ Class<?> fTestClass;

    private Description(Class<?> clazz, String displayName, Annotation... annotations) {
        this(clazz, displayName, displayName, annotations);
    }

    private Description(Class<?> testClass, String displayName, Serializable uniqueId, Annotation... annotations) {
        if ((displayName == null) || (displayName.length() == 0)) {
            throw new IllegalArgumentException(
                    "The display name must not be empty.");
        }
        if ((uniqueId == null)) {
            throw new IllegalArgumentException(
                    "The unique id must not be null.");
        }
        this.fTestClass = testClass;
        this.fDisplayName = displayName;
        this.fUniqueId = uniqueId;
        this.fAnnotations = annotations;
    }

    /**
     * @return a user-understandable label
     */
    public String getDisplayName() {
        return fDisplayName;
    }

    /**
     * Add <code>Description</code> as a child of the receiver.
     *
     * @param description the soon-to-be child.
     */
    public void addChild(Description description) {
        fChildren.add(description);
    }

    /**
     * Gets the copy of the children of this {@code Description}.
     * Returns an empty list if there are no children.
     */
    public ArrayList<Description> getChildren() {
        return new ArrayList<Description>(fChildren);
    }

    /**
     * @return <code>true</code> if the receiver is a suite
     */
    public boolean isSuite() {
        return !isTest();
    }

    /**
     * @return <code>true</code> if the receiver is an atomic test
     */
    public boolean isTest() {
        return fChildren.isEmpty();
    }

    /**
     * @return the total number of atomic tests in the receiver
     */
    public int testCount() {
        if (isTest()) {
            return 1;
        }
        int result = 0;
        for (Description child : fChildren) {
            result += child.testCount();
        }
        return result;
    }

    @Override
    public int hashCode() {
        return fUniqueId.hashCode();
    }

    @Override
    public boolean equals(Object obj) {
        if (!(obj instanceof Description)) {
            return false;
        }
        Description d = (Description) obj;
        return fUniqueId.equals(d.fUniqueId);
    }

    @Override
    public String toString() {
        return getDisplayName();
    }

    /**
     * @return true if this is a description of a Runner that runs no tests
     */
    public boolean isEmpty() {
        return equals(EMPTY);
    }

    /**
     * @return a copy of this description, with no children (on the assumption that some of the
     *         children will be added back)
     */
    public Description childlessCopy() {
        return new Description(fTestClass, fDisplayName, fAnnotations);
    }

    /**
     * @return the annotation of type annotationType that is attached to this description node,
     *         or null if none exists
     */
    public <T extends Annotation> T getAnnotation(Class<T> annotationType) {
        for (Annotation each : fAnnotations) {
            if (each.annotationType().equals(annotationType)) {
                return annotationType.cast(each);
            }
        }
        return null;
    }

    /**
     * @return all of the annotations attached to this description node
     */
    public Collection<Annotation> getAnnotations() {
        return Arrays.asList(fAnnotations);
    }

    /**
     * @return If this describes a method invocation,
     *         the class of the test instance.
     */
    public Class<?> getTestClass() {
        if (fTestClass != null) {
            return fTestClass;
        }
        String name = getClassName();
        if (name == null) {
            return null;
        }
        try {
            fTestClass = Class.forName(name, false, getClass().getClassLoader());
            return fTestClass;
        } catch (ClassNotFoundException e) {
            return null;
        }
    }

    /**
     * @return If this describes a method invocation,
     *         the name of the class of the test instance
     */
    public String getClassName() {
        return fTestClass != null ? fTestClass.getName() : methodAndClassNamePatternGroupOrDefault(2, toString());
    }

    /**
     * @return If this describes a method invocation,
     *         the name of the method (or null if not)
     */
    public String getMethodName() {
        return methodAndClassNamePatternGroupOrDefault(1, null);
    }

    private String methodAndClassNamePatternGroupOrDefault(int group,
            String defaultString) {
        Matcher matcher = METHOD_AND_CLASS_NAME_PATTERN.matcher(toString());
        return matcher.matches() ? matcher.group(group) : defaultString;
    }
}