/*
 * 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 static 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);
            }
        }
    }
}
