/*
 * Copyright (c) 2006, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation
//
package org.eclipse.persistence.jpa.tests.jpql;

import java.lang.annotation.Annotation;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.persistence.jpa.jpql.tools.model.AbstractActualJPQLQueryFormatter;
import org.eclipse.persistence.jpa.jpql.tools.model.BaseJPQLQueryFormatter;
import org.eclipse.persistence.jpa.jpql.tools.model.IJPQLQueryBuilder;
import org.eclipse.persistence.jpa.tests.jpql.parser.JPQLGrammarTestHelper;
import org.eclipse.persistence.jpa.tests.jpql.tools.model.IJPQLQueryBuilderTestHelper;
import org.eclipse.persistence.jpa.tests.jpql.tools.model.IJPQLQueryFormatterTestHelper;
import org.junit.internal.builders.AllDefaultPossibilitiesBuilder;
import org.junit.internal.runners.ErrorReportingRunner;
import org.junit.runner.Description;
import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.ParentRunner;
import org.junit.runners.Suite.SuiteClasses;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;

/**
 * This JUnit runner is the sole runner of Hermes unit-tests because it modifies the default
 * behavior by adding the following support:
 * <ul>
 * <li>Adds the ability to inject objects that are instantiated by a test suite into the unit-test
 * before they are run.
 * <li>Because one unit-test can be run more than once with different state of any given object,
 * this cause issues in Eclipse because the IDE uses {@link Object#toString()} and cannot
 * discriminate between those identical tests. This runner changes the test's description by adding
 * enough information in order to make each test's description unique.
 * </ul>
 *
 * @version 2.4
 * @since 2.4
 * @author Pascal Filion
 */
@SuppressWarnings({ "nls", "restriction" })
public class JPQLTestRunner extends ParentRunner<Runner> {

    /**
     * The cached {@link Description} so it's not recreated every time.
     */
    private Description description;

    /**
     * This contains the helpers that will be injected into each test.
     */
    private DescriptionHelper descriptionHelper;

    /**
     * The display string of this test suite.
     */
    private String name;

    /**
     * The {@link Runner runners} for the test classes defined in {@link org.junit.runners.Suite.SuiteClasses
     * &#64;SuiteClasses}.
     */
    private List<Runner> runners;

    /**
     * The parent {@link SuiteHelper} or <code>null</code> if none was defined yet.
     */
    private SuiteHelper suiteHelper;

    /**
     * The list of registered helpers that inject values from the test suite into the unit-tests
     * before they are running.
     */
    private static final Map<Class<? extends Annotation>, DescriptionBuilder> testRunnerHelpers;

    /**
     * Registers the supported test runner helpers.
     */
    static {

        testRunnerHelpers = new HashMap<>();

        testRunnerHelpers.put(IJPQLQueryBuilderTestHelper.class,   buildJPQLQueryBuilderTestHelperDescriptionBuilder());
        testRunnerHelpers.put(IJPQLQueryFormatterTestHelper.class, buildJPQLQueryFormatterTestHelperDescriptionBuilder());
        testRunnerHelpers.put(JPQLGrammarTestHelper.class,         buildJPQLGrammarTestHelperDescriptionBuilder());
        testRunnerHelpers.put(JPQLQueryHelperTestHelper.class,     buildJPQLQueryHelperTestHelperDescriptionBuilder());
        testRunnerHelpers.put(JPQLQueryTestHelperTestHelper.class, buildJPQLQueryTestHelperTestHelperDescriptionBuilder());
    }

    /**
     * Creates a new <code>JPQLTestRunner</code>.
     *
     * @param testClass The class that is either a test suite or a unit-tests
     * @throws InitializationError If the given test class is malformed
     */
    public JPQLTestRunner(Class<?> testClass) throws InitializationError {
        super(testClass);
    }

    /**
     * Creates a new <code>JPQLTestRunner</code>.
     *
     * @param testClass The class that is either a test suite or a unit-tests
     * @param suiteHelper The parent {@link SuiteHelper} or {@code null} if none was defined yet
     * @throws InitializationError If the given test class is malformed
     */
    public JPQLTestRunner(Class<?> testClass, SuiteHelper suiteHelper) throws InitializationError {
        this(testClass);
        this.suiteHelper = suiteHelper;
    }

    private static DescriptionBuilder buildJPQLGrammarTestHelperDescriptionBuilder() {
        return new DescriptionBuilder() {
            @Override
            public String toString(Object object) {
                return object.toString();
            }
        };
    }

    private static DescriptionBuilder buildJPQLQueryBuilderTestHelperDescriptionBuilder() {
        return new DescriptionBuilder() {
            @Override
            public String toString(Object object) {
                IJPQLQueryBuilder builder = (IJPQLQueryBuilder) object;
                StringBuilder sb = new StringBuilder();
                sb.append(builder.getClass().getSimpleName());
                sb.append("[");
                sb.append(builder.getGrammar().toString());
                sb.append("]");
                return sb.toString();
            }
        };
    }

    private static DescriptionBuilder buildJPQLQueryFormatterTestHelperDescriptionBuilder() {
        return new DescriptionBuilder() {
            @Override
            public String toString(Object object) {
                BaseJPQLQueryFormatter formatter = (BaseJPQLQueryFormatter) object;
                StringBuilder sb = new StringBuilder();
                sb.append(formatter.getClass().getSimpleName());
                sb.append("[");
                sb.append(formatter.getIdentifierStyle().name());
                if (object instanceof AbstractActualJPQLQueryFormatter) {
                    AbstractActualJPQLQueryFormatter actualFormatter = (AbstractActualJPQLQueryFormatter) object;
                    sb.append("|");
                    sb.append(actualFormatter.isUsingExactMatch());
                }
                sb.append("]");
                return sb.toString();
            }
        };
    }

    private static DescriptionBuilder buildJPQLQueryHelperTestHelperDescriptionBuilder() {
        return new DescriptionBuilder() {
            @Override
            public String toString(Object object) {
                return object.getClass().getSimpleName();
            }
        };
    }

    private static DescriptionBuilder buildJPQLQueryTestHelperTestHelperDescriptionBuilder() {
        return new DescriptionBuilder() {
            @Override
            public String toString(Object object) {
                return object.getClass().getSimpleName();
            }
        };
    }

    private List<Runner> buildChildren() {

        SuiteClasses suiteClasses = findSuiteClasses(getTestClass().getJavaClass());

        if (suiteClasses == null) {
            return Collections.emptyList();
        }

        List<Runner> runners = new ArrayList<>();

        for (Class<?> test : suiteClasses.value()) {
            if (descriptionHelper.helpers.isEmpty()) {
                Runner runner = buildRunner(test, suiteHelper);
                runners.add(runner);
            }
            else {
                for (SuiteHelper suiteHelper : buildSuiteHelpers()) {
                    Runner runner = buildRunner(test, suiteHelper);
                    runners.add(runner);
                }
            }
        }

        Collections.sort(runners, buildRunnerComparator());
        return runners;
    }

    private String buildDisplayString() {

        String displayString = super.getName();

        if (suiteHelper != null) {
            StringBuilder writer = new StringBuilder();
            writer.append(displayString);
            suiteHelper.addAdditionalInfo(writer);
            displayString = writer.toString();
        }

        return displayString;
    }

    private Runner buildRunner(Class<?> testClass, SuiteHelper suiteHelper) {

        try {

            // Create a runner for multiple unit-tests
            SuiteClasses suiteClasses = findSuiteClasses(testClass);

            if (suiteClasses != null) {
                return new JPQLTestRunner(testClass, suiteHelper);
            }

            // Create a runner for a single unit-test
            if (JPQLBasicTest.class.isAssignableFrom(testClass)) {
                return new JPQLBasicTestRunner(testClass, suiteHelper);
            }

            // Create the default runner
            return new AllDefaultPossibilitiesBuilder().runnerForClass(testClass);
        }
        catch (Throwable e) {
            return new ErrorReportingRunner(testClass, e);
        }
    }

    private Comparator<Runner> buildRunnerComparator() {
        return new Comparator<Runner>() {
            @Override
            public int compare(Runner runner1, Runner runner2) {
                String displayName1 = runner1.getDescription().getDisplayName();
                String displayName2 = runner1.getDescription().getDisplayName();
                return displayName1.compareTo(displayName2);
            }
        };
    }

    private List<SuiteHelper> buildSuiteHelpers() {

        List<SuiteHelper> suiteHelpers = new ArrayList<>();
        Map<Class<? extends Annotation>, Object> singleHelpers = new HashMap<>();
        Collection<Class<? extends Annotation>> multipleHelpers = retrieveMultipleHelpers();

        for (Map.Entry<Class<? extends Annotation>, Object[]> helper : descriptionHelper.helpers.entrySet()) {
            if (!multipleHelpers.contains(helper.getKey())) {
                singleHelpers.put(helper.getKey(), helper.getValue()[0]);
            }
        }

        if (multipleHelpers.size() > 1) {
            for (Class<? extends Annotation> firstHelperKey : multipleHelpers) {
                for (Class<? extends Annotation> secondHelperKey : multipleHelpers) {
                    if (firstHelperKey != secondHelperKey) {
                        for (Object firstHelper : descriptionHelper.helpers.get(firstHelperKey)) {
                            for (Object secondHelper : descriptionHelper.helpers.get(secondHelperKey)) {
                                Map<Class<? extends Annotation>, Object> copy = new HashMap<>();
                                copy.putAll(singleHelpers);
                                copy.put(firstHelperKey,  firstHelper);
                                copy.put(secondHelperKey, secondHelper);

                                List<Class<? extends Annotation>> keys = new ArrayList<>();
                                keys.add(firstHelperKey);
                                keys.add(secondHelperKey);

                                suiteHelpers.add(new SuiteHelper(suiteHelper, copy, keys));
                            }
                        }
                    }
                }
            }
        }
        else if (multipleHelpers.size() == 1) {
            for (Class<? extends Annotation> firstHelperKey : multipleHelpers) {
                for (Object firstHelper : descriptionHelper.helpers.get(firstHelperKey)) {
                    Map<Class<? extends Annotation>, Object> copy = new HashMap<>();
                    copy.putAll(singleHelpers);
                    copy.put(firstHelperKey, firstHelper);

                    List<Class<? extends Annotation>> keys = new ArrayList<>();
                    keys.add(firstHelperKey);

                    suiteHelpers.add(new SuiteHelper(suiteHelper, copy, keys));
                }
            }
        }
        else {
            suiteHelpers.add(new SuiteHelper(suiteHelper, singleHelpers));
        }

        return suiteHelpers;
    }

    @Override
    protected void collectInitializationErrors(List<Throwable> errors) {
        super.collectInitializationErrors(errors);
        initializeDescriptionHelper(errors);
    }

    @Override
    protected Description describeChild(Runner child) {
        return child.getDescription();
    }

    private SuiteClasses findSuiteClasses(Class<?> testClass) {

        if (testClass == Object.class) {
            return null;
        }

        SuiteClasses suiteClasses = testClass.getAnnotation(SuiteClasses.class);

        if (suiteClasses != null) {
            return suiteClasses;
        }

        return findSuiteClasses(testClass.getSuperclass());
    }

    @Override
    protected List<Runner> getChildren() {
        // Cache the Description since JUnit always recreate it, this will increase performance
        if (runners == null) {
            runners = buildChildren();
        }
        return runners;
    }

    @Override
    public Description getDescription() {
        // Cache the Description since JUnit always recreate it, this will increase performance
        if (description == null) {
            description = super.getDescription();
        }
        return description;
    }

    @Override
    protected String getName() {
        // Cache the Description since JUnit always recreate it, this will increase performance and
        // also, add the extra information otherwise Eclipse will not be able to update the status of
        // the tests, it uses the display string to retrieve the node from the JUnit view, if two
        // nodes have the same display string, then only the last one is updated
        if (name == null) {
            name = buildDisplayString();
        }
        return name;
    }

    private void initializeDescriptionHelper(List<Throwable> errors) {

        descriptionHelper = new DescriptionHelper();
        Class<?> unitTest = getTestClass().getJavaClass();

        for (Method method : unitTest.getDeclaredMethods()) {

            if (isHelperMethod(method)) {

                for (Class<? extends Annotation> annotation : testRunnerHelpers.keySet()) {

                    if (method.isAnnotationPresent(annotation)) {

                        try {
                            method.setAccessible(true);
                            Object value = method.invoke(null);

                            descriptionHelper.helpers.put(
                                annotation,
                                value.getClass().isArray() ? (Object[]) value : new Object[] { value }
                            );
                        }
                        catch (Exception e) {
                            errors.add(e);
                        }
                    }
                }
            }
        }
    }

    private boolean isHelperMethod(Method method) {
        return Modifier.isStatic(method.getModifiers());
    }

    private Collection<Class<? extends Annotation>> retrieveMultipleHelpers() {

        Collection<Class<? extends Annotation>> keys = new ArrayList<>();

        for (Map.Entry<Class<? extends Annotation>, Object[]> helper : descriptionHelper.helpers.entrySet()) {
            if (helper.getValue().length > 1) {
                keys.add(helper.getKey());
            }
        }

        return keys;
    }

    @Override
    protected void runChild(Runner child, RunNotifier notifier) {
        child.run(notifier);
    }

    /**
     * This interface is used to create the description of a unit-tests.
     */
    private interface DescriptionBuilder {

        /**
         * Creates a string representation of the given object.
         *
         * @param object The object to convert into a human readable string
         * @return A unique description for the given object
         */
        String toString(Object object);
    }

    private static class DescriptionHelper {

        private Map<Class<? extends Annotation>, Object[]> helpers;

        DescriptionHelper() {
            super();
            helpers = new HashMap<>();
        }
    }

    private static class JPQLBasicTestRunner extends BlockJUnit4ClassRunner {

        private Description description;
        private SuiteHelper suiteHelper;
        private JPQLBasicTest test;
        private boolean uniquenessRequired;

        JPQLBasicTestRunner(Class<?> testClass, SuiteHelper suiteHelper) throws InitializationError {
            super(testClass);
            this.suiteHelper = suiteHelper;
            // Check to see if the signature of the test methods needs to be unique,
            // this is required when the same test is run more than once and the
            // generated signature remains identical
            uniquenessRequired = testClass.isAnnotationPresent(UniqueSignature.class);
        }

        private Description buildDescription() {

            Description description = Description.createSuiteDescription(
                buildDisplayString(),
                getTestClass().getAnnotations()
            );

            Description superDescription = super.getDescription();
            description.getChildren().addAll(superDescription.getChildren());

            return description;
        }

        private String buildDisplayString() {
            if (suiteHelper != null) {
                StringBuilder writer = new StringBuilder();
                writer.append(getName());
                suiteHelper.addAdditionalInfo(writer);
                return writer.toString();
            }
            return getName();
        }

        private Comparator<FrameworkMethod> buildMethodComparator() {
            return new Comparator<FrameworkMethod>() {
                @Override
                public int compare(FrameworkMethod method1, FrameworkMethod method2) {
                    return method1.getName().compareTo(method2.getName());
                }
            };
        }

        @Override
        protected Statement classBlock(RunNotifier notifier) {
            Statement statement = new CreateTestStatement();
            statement = new SetUpClassStatement(statement);
            statement = new CompositeStatement(statement, childrenInvoker(notifier));
            statement = new TearDownClassStatement(statement);
            return statement;
        }

        @Override
        protected Object createTest() {
            return test;
        }

        @Override
        protected List<FrameworkMethod> getChildren() {
            List<FrameworkMethod> methods = new ArrayList<>(super.getChildren());
            Collections.sort(methods, buildMethodComparator());
            return methods;
        }

        @Override
        public Description getDescription() {
            if (description == null) {
                description = buildDescription();
            }
            return description;
        }

        private void instantiateTest() throws Throwable {

            Class<?> testClass = getTestClass().getJavaClass();
            Constructor<?> constructor = testClass.getConstructor();
            constructor.setAccessible(true);
            test = (JPQLBasicTest) constructor.newInstance();

            // Inject the SuiteHelper' values into the test
            if (suiteHelper != null) {
                suiteHelper.injectValues(test);
            }
        }

        @Override
        protected Statement methodBlock(FrameworkMethod method) {
            Statement statement = new SetUpStatement();
            statement = new CompositeStatement(statement, super.methodBlock(method));
            statement = new TearDownStatement(statement);
            return statement;
        }

        @Override
        protected Statement methodInvoker(FrameworkMethod method, Object test) {
            this.test = (JPQLBasicTest) test;
            return super.methodInvoker(method, test);
        }

        @Override
        protected String testName(FrameworkMethod method) {

            // Create the signature of the method, which will have the helpers' additional information
            StringBuilder writer = new StringBuilder();
            writer.append(method.getName());

            if (suiteHelper != null) {
                suiteHelper.addAdditionalInfo(writer);
            }

            // It is possible two signatures maybe be identical, add something unique
            if (uniquenessRequired) {
                writer.append(" (");
                writer.append(hashCode());
                writer.append(")");
            }

            return writer.toString();
        }

        private class CompositeStatement extends Statement {

            private Statement statement1;
            private Statement statement2;

            CompositeStatement(Statement statement1, Statement statement2) {
                super();
                this.statement1 = statement1;
                this.statement2 = statement2;
            }


            @Override
            public void evaluate() throws Throwable {
                statement1.evaluate();
                statement2.evaluate();
            }
        }

        /**
         * This {@link Statement} evaluates the wrapped {@link Statement} and then invoke {@link
         * JPQLBasicTest#setUpClass()}.
         */
        private class CreateTestStatement extends Statement {
            @Override
            public void evaluate() throws Throwable {
                instantiateTest();
            }
        }

        /**
         * This {@link Statement} evaluates the wrapped {@link Statement} and then invoke {@link
         * JPQLBasicTest#setUpClass()}.
         */
        private class SetUpClassStatement extends Statement {

            private Statement statement;

            SetUpClassStatement(Statement statement) {
                super();
                this.statement = statement;
            }


            @Override
            public void evaluate() throws Throwable {
                statement.evaluate();
                test.setUpClass();
            }
        }

        /**
         * This {@link Statement} evaluates the wrapped {@link Statement} and then invoke {@link
         * JPQLBasicTest#setUp()}.
         */
        private class SetUpStatement extends Statement {
            @Override
            public void evaluate() throws Throwable {
                test.setUp();
            }
        }

        /**
         * This {@link Statement} evaluates the wrapped {@link Statement} and then invoke {@link
         * JPQLBasicTest#tearDownClass()}.
         */
        private class TearDownClassStatement extends Statement {

            private Statement statement;

            TearDownClassStatement(Statement statement) {
                super();
                this.statement = statement;
            }


            @Override
            public void evaluate() throws Throwable {
                try {
                    statement.evaluate();
                }
                finally {
                    if (test != null) {
                        test.tearDownClass();
                    }
                }
            }
        }

        /**
         * This {@link Statement} evaluates the wrapped {@link Statement} and then invoke {@link
         * JPQLBasicTest#tearDown()}.
         */
        private class TearDownStatement extends Statement {

            private Statement statement;

            TearDownStatement(Statement statement) {
                super();
                this.statement = statement;
            }


            @Override
            public void evaluate() throws Throwable {
                try {
                    statement.evaluate();
                }
                finally {
                    if (test != null) {
                        test.tearDown();
                    }
                }
            }
        }
    }

    private static class SuiteHelper {

        private Map<Class<? extends Annotation>, Object> helpers;
        private SuiteHelper parent;
        private List<Class<? extends Annotation>> primaryKeys;

        SuiteHelper(SuiteHelper parent,
                    Map<Class<? extends Annotation>, Object> helpers) {

            this(parent, helpers, Collections.<Class<? extends Annotation>>emptyList());
        }

        SuiteHelper(SuiteHelper parent,
                    Map<Class<? extends Annotation>, Object> helpers,
                    List<Class<? extends Annotation>> primaryKeys) {

            super();
            this.parent      = parent;
            this.helpers     = helpers;
            this.primaryKeys = primaryKeys;
        }

        void addAdditionalInfo(StringBuilder writer) {

            for (Class<? extends Annotation> primaryKey : primaryKeys) {
                writer.append(" - ");
                Object helper = helpers.get(primaryKey);
                DescriptionBuilder descriptionBuilder = testRunnerHelpers.get(primaryKey);
                writer.append(descriptionBuilder.toString(helper));
            }

            if (parent != null) {
                parent.addAdditionalInfo(writer);
            }
        }

        private void injectValues(Class<?> testClass, JPQLBasicTest test) throws Exception {

            if (testClass == Object.class) {
                return;
            }

            Field[] fields = testClass.getDeclaredFields();

            for (Field field : fields) {
                for (Map.Entry<Class<? extends Annotation>, Object> helper : helpers.entrySet()) {
                    if (field.isAnnotationPresent(helper.getKey())) {
                        field.setAccessible(true);
                        field.set(test, helper.getValue());
                    }
                }
            }

            injectValues(testClass.getSuperclass(), test);
        }

        void injectValues(JPQLBasicTest test) throws Exception {

            injectValues(test.getClass(), test);

            if (parent != null) {
                parent.injectValues(test);
            }
        }
    }
}
