/*
 * Copyright (c) 2005, 2020 Oracle and/or its affiliates. All rights reserved.
 * Copyright (c) 2005, 2015 SAP. 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:
//     SAP - initial API and implementation

package org.eclipse.persistence.testing.framework.wdf;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.rmi.PortableRemoteObject;

import org.eclipse.persistence.config.PersistenceUnitProperties;
import org.eclipse.persistence.platform.database.DatabasePlatform;
import org.eclipse.persistence.testing.framework.wdf.customizer.AdjustArrayTypeCustomizer;
import org.eclipse.persistence.testing.framework.wdf.server.Notification;
import org.eclipse.persistence.testing.framework.wdf.server.ServerTestRunner;
import org.junit.Assert;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.model.FrameworkMethod;

public class SkipBugzillaTestRunner extends BlockJUnit4ClassRunner {

    private static final String TEST_TO_BE_INVESTIGATED_RUN = "test.to-be-investigated.run";
    private static final String TEST_ISSUE_RUN = "test.issue.run";
    private static final String TEST_BUGZILLA_RUN = "test.bugzilla.run";


    @Override
    public void run(RunNotifier notifier) {
        if (Boolean.valueOf(System.getProperty("servertest"))) {
            runOnServer(notifier);
        } else {
            super.run(notifier);
        }
    }

    /**
     * Delegates test execution to the server. On the server, JUnit will be
     * invoked to run the tests with a special run listener, which collects
     * the notifications (events). On the client, the recorded notifications will be
     * replayed on the run notifier passed to this message.
     * @param notifier the run notifier to replay the notifications recorded on the server
     */
    private void runOnServer(RunNotifier notifier) {
        Properties properties = new Properties();
        String url = getMandatorySystemProperty("server.url");
        properties.put("java.naming.provider.url", url);
        Context context;
        try {
            context = new InitialContext(properties);
            String testrunner = getMandatorySystemProperty("server.testrunner.wdf");
            String dataSourceName = getMandatorySystemProperty("datasource.name");

            Object object = context.lookup(testrunner);
            ServerTestRunner runner = (ServerTestRunner) PortableRemoteObject.narrow(object, ServerTestRunner.class);
            String testClassName = getTestClass().getJavaClass().getName();
            List<Notification> notifications = runner.runTestClass(testClassName, dataSourceName, testProperties);

            for (Notification notification : notifications) {
                notification.notify(notifier);
            }
        } catch (NamingException e) {
            throw new RuntimeException(e);
        }
    }

    private String getMandatorySystemProperty(final String propertyName) {
        String url = System.getProperty(propertyName);
        if (url == null) {
            Assert.fail("System property '" + propertyName + "' must be set.");
        }
        return url;
    }

    final long bugid;
    final long issueid;
    final boolean runAllBugzilla;
    final boolean runAllIssues;
    final boolean runAllUnknown;
    final boolean runOnlyUnknown;
    final Class<? extends DatabasePlatform> databasePlatformClass;
    private final Map<String, String> testProperties;


    @SuppressWarnings("unchecked")
    public SkipBugzillaTestRunner(Class<?> klass) throws Throwable {
        super(klass);

        testProperties = AbstractBaseTest.getTestProperties();


        addProperty(TEST_BUGZILLA_RUN);
        addProperty(TEST_ISSUE_RUN);
        addProperty(TEST_TO_BE_INVESTIGATED_RUN);

        String databasePlatformClassName = testProperties.get(PersistenceUnitProperties.TARGET_DATABASE);


        if (databasePlatformClassName != null) {
            databasePlatformClass = (Class<? extends DatabasePlatform>) Class.forName(databasePlatformClassName);
            AdjustArrayTypeCustomizer.setDatabasePlatformClass(databasePlatformClass);
        } else {
            databasePlatformClass = null; // FIXME
        }

        String testBugzillaRun = (String) testProperties.get(TEST_BUGZILLA_RUN);
        if ("all".equals(testBugzillaRun)) {
            runAllBugzilla = true;
            bugid = -1;
        } else {
            runAllBugzilla = false;
            if (testBugzillaRun != null) {
                bugid = Long.parseLong(testBugzillaRun);
            } else {
                bugid = -1;
            }
        }

        String testIssueRun = (String) testProperties.get(TEST_ISSUE_RUN);
        if ("all".equals(testIssueRun)) {
            runAllIssues = true;
            issueid = -1;
        } else {
            runAllIssues = false;
            if (testIssueRun != null) {
                issueid = Long.parseLong(testIssueRun);
            } else {
                issueid = -1;
            }
        }

        String testToBeInvestigatedRun = (String) testProperties.get(TEST_TO_BE_INVESTIGATED_RUN);
        if ("all".equals(testToBeInvestigatedRun)) {
            runAllUnknown = true;
            runOnlyUnknown = false;
        } else if ("only".equals(testToBeInvestigatedRun)) {
            runAllUnknown = false;
            runOnlyUnknown = true;
        } else {
            runAllUnknown = false;
            runOnlyUnknown = false;
        }


    }

    private void addProperty(final String name) {
        String value = System.getProperty(name);
        if(value != null) {
            testProperties.put(name, value);
        }
    }

    @Override
    protected void runChild(FrameworkMethod method, RunNotifier notifier) {
        try {
            skipMethod(method, notifier, SKIP_SKIPPER);
            skipMethod(method, notifier, BUGZILLA_SKIPPER);
            skipMethod(method, notifier, ISSUE_SKIPPER);
            skipMethod(method, notifier, TO_BE_INVESTIGATED_SKIPPER);
            super.runChild(method, notifier);
        } catch (SkipException ex) {
            Description description = describeChild(method);
            notifier.fireTestIgnored(description);
        }
    }

    private <T extends Annotation> void skipMethod(FrameworkMethod method, RunNotifier notifier, Skipper<T> skipper)
            throws SkipException {
        Method reflectMethod = method.getMethod();
        T a = skipper.getAnnotation(reflectMethod);
        if (a == null) {
            if (skipper.skipOthers()) {
                throw new SkipException();
            }
            return;
        }

        if (skipper.runAll()) {
            return;
        }

        if (skipper.runThis(a)) {
            return;
        }

        Class<? extends DatabasePlatform>[] databases = skipper.getDatabases(a);
        String[] databaseNames = skipper.getDatabaseNames(a);

        if ((databases == null || databases.length == 0) && (databaseNames == null || databaseNames.length == 0)) {
            // all databases are unsupported
            throw new SkipException();
        }

        if (databasePlatformClass != null) {
            if (databases != null) {
                for (Class<? extends DatabasePlatform> clazz : databases) {
                    if (clazz.isAssignableFrom(databasePlatformClass)) {
                        // the current database platform is not supported
                        throw new SkipException();
                    }
                }
            }

            if (databaseNames != null) {
                for (String name : databaseNames) {
                    if (databasePlatformClass.getName().equals(name)) {
                        // the current database platform is not supported
                        throw new SkipException();
                    }
                }
            }
        }

        return;
    }

    private static class SkipException extends Exception {
        private static final long serialVersionUID = 1L;
    }

    private Skipper<Skip> SKIP_SKIPPER = new Skipper<Skip>() {

        @Override
        public Skip getAnnotation(Method method) {
            return method.getAnnotation(Skip.class);
        }

        @Override
        public Class<? extends DatabasePlatform>[] getDatabases(Skip skip) {
            return skip.databases();
        }

        @Override
        public boolean runAll() {
            return false;
        }

        @Override
        public boolean runThis(Skip skip) {

            if(skip.server()) {
                return !ServerInfoHolder.isOnServer();
            }

            return false;
        }

        @Override
        public boolean skipOthers() {
            return false;
        }

        @Override
        public String[] getDatabaseNames(Skip skip) {
            return skip.databaseNames();
        }

    };

    private final Skipper<Bugzilla> BUGZILLA_SKIPPER = new Skipper<Bugzilla>() {

        @Override
        public Bugzilla getAnnotation(Method method) {
            return method.getAnnotation(Bugzilla.class);
        }

        @Override
        public Class<? extends DatabasePlatform>[] getDatabases(Bugzilla t) {
            return t.databases();
        }

        @Override
        public boolean runAll() {
            return runAllBugzilla;
        }

        @Override
        public boolean runThis(Bugzilla t) {
            return t.bugid() == bugid;
        }

        @Override
        public boolean skipOthers() {
            return false;
        }

        @Override
        public String[] getDatabaseNames(Bugzilla t) {
            return t.databaseNames();
        }

    };

    private final Skipper<Issue> ISSUE_SKIPPER = new Skipper<Issue>() {

        @Override
        public Issue getAnnotation(Method method) {
            return method.getAnnotation(Issue.class);
        }

        @Override
        public Class<? extends DatabasePlatform>[] getDatabases(Issue t) {
            return t.databases();
        }

        @Override
        public boolean runAll() {
            return runAllIssues;
        }

        @Override
        public boolean runThis(Issue t) {
            return t.issueid() == issueid;
        }

        @Override
        public boolean skipOthers() {
            return false;
        }

        @Override
        public String[] getDatabaseNames(Issue t) {
            return t.databaseNames();
        }

    };

    private final Skipper<ToBeInvestigated> TO_BE_INVESTIGATED_SKIPPER = new Skipper<ToBeInvestigated>() {

        @Override
        public ToBeInvestigated getAnnotation(Method method) {
            return method.getAnnotation(ToBeInvestigated.class);
        }

        @Override
        public Class<? extends DatabasePlatform>[] getDatabases(ToBeInvestigated t) {
            return t.databases();
        }

        @Override
        public boolean runAll() {
            return runAllUnknown || runOnlyUnknown;
        }

        @Override
        public boolean runThis(ToBeInvestigated t) {
            return false;
        }

        @Override
        public boolean skipOthers() {
            return runOnlyUnknown;
        }

        @Override
        public String[] getDatabaseNames(ToBeInvestigated t) {
            return t.databaseNames();
        }

    };

    private interface Skipper<T extends Annotation> {
        T getAnnotation(Method method);

        boolean runAll();

        boolean runThis(T t);

        boolean skipOthers();

        Class<? extends DatabasePlatform>[] getDatabases(T t);

        String[] getDatabaseNames(T t);
    }


}
