/*
 * Copyright (C) 2009 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package vogar.target;

import com.google.common.annotations.VisibleForTesting;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Properties;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.annotation.Nullable;
import vogar.Result;
import vogar.RunnerType;
import vogar.TestProperties;
import vogar.monitor.TargetMonitor;
import vogar.target.junit.JUnitRunnerFactory;

/**
 * Runs an action, in process on the target.
 */
public final class TestRunner {

    private final String qualifiedClassOrPackageName;

    /** the monitor port if a monitor is expected, or null for no monitor */
    @VisibleForTesting final Integer monitorPort;

    /** use an atomic reference so the runner can null it out when it is encountered. */
    private final AtomicReference<String> skipPastReference;
    private final int timeoutSeconds;

    private final RunnerFactory runnerFactory;
    private final boolean profile;
    private final int profileDepth;
    private final int profileInterval;
    private final File profileFile;
    private final boolean profileThreadGroup;
    private final String[] args;
    private boolean useSocketMonitor;

    public TestRunner(Properties properties, List<String> argsList) {
        qualifiedClassOrPackageName = properties.getProperty(TestProperties.TEST_CLASS_OR_PACKAGE);
        timeoutSeconds = Integer.parseInt(properties.getProperty(TestProperties.TIMEOUT));

        int monitorPort = Integer.parseInt(properties.getProperty(TestProperties.MONITOR_PORT));
        String skipPast = null;
        boolean profile = Boolean.parseBoolean(properties.getProperty(TestProperties.PROFILE));
        int profileDepth = Integer.parseInt(properties.getProperty(TestProperties.PROFILE_DEPTH));
        int profileInterval
                = Integer.parseInt(properties.getProperty(TestProperties.PROFILE_INTERVAL));
        File profileFile = new File(properties.getProperty(TestProperties.PROFILE_FILE));
        boolean profileThreadGroup
                = Boolean.parseBoolean(properties.getProperty(TestProperties.PROFILE_THREAD_GROUP));

        for (Iterator<String> i = argsList.iterator(); i.hasNext(); ) {
            String arg = i.next();
            if (arg.equals("--monitorPort")) {
                i.remove();
                monitorPort = Integer.parseInt(i.next());
                i.remove();
            }
            if (arg.equals("--skipPast")) {
                i.remove();
                skipPast = i.next();
                i.remove();
            }
        }

        // Select the RunnerFactory instances to use based on the selected runner type.
        RunnerType runnerType =
                RunnerType.valueOf(properties.getProperty(TestProperties.RUNNER_TYPE));
        List<RunnerFactory> runnerFactories = new ArrayList<>();
        if (runnerType.supportsCaliper()) {
            runnerFactories.add(new CaliperRunnerFactory(argsList));
        }
        if (runnerType.supportsJUnit()) {
            runnerFactories.add(new JUnitRunnerFactory());
        }
        if (runnerType.supportsMain()) {
            runnerFactories.add(new MainRunnerFactory());
        }
        runnerFactory = new CompositeRunnerFactory(runnerFactories);

        this.monitorPort = monitorPort;
        this.skipPastReference = new AtomicReference<>(skipPast);
        this.profile = profile;
        this.profileDepth = profileDepth;
        this.profileInterval = profileInterval;
        this.profileFile = profileFile;
        this.profileThreadGroup = profileThreadGroup;
        this.args = argsList.toArray(new String[argsList.size()]);
    }

    /**
     * Load the properties that were either encapsulated in the APK (if using
     * {@link vogar.android.ActivityMode}), or encapsulated in the JAR compiled by Vogar (in other
     * modes).
     *
     * @return The {@link Properties} that were loaded.
     */
    public static Properties loadProperties() {
        try {
            InputStream in = getPropertiesStream();
            Properties properties = new Properties();
            properties.load(in);
            in.close();
            return properties;
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Configure this test runner to await an incoming socket connection when
     * writing test results. Otherwise all communication happens over
     * System.out.
     */
    public void useSocketMonitor() {
        this.useSocketMonitor = true;
    }

    /**
     * Attempt to load the test properties file from both the application and system classloader.
     * This is necessary because sometimes we run tests from the boot classpath.
     */
    private static InputStream getPropertiesStream() throws IOException {
        for (Class<?> classToLoadFrom : new Class<?>[] { TestRunner.class, Object.class }) {
            InputStream propertiesStream = classToLoadFrom.getResourceAsStream(
                    "/" + TestProperties.FILE);
            if (propertiesStream != null) {
                return propertiesStream;
            }
        }
        throw new IOException(TestProperties.FILE + " missing!");
    }

    public void run() throws IOException {
        final TargetMonitor monitor = useSocketMonitor
                ? TargetMonitor.await(monitorPort)
                : TargetMonitor.forPrintStream(System.out);

        PrintStream monitorPrintStream = new PrintStreamDecorator(System.out) {
            @Override public void print(String str) {
                monitor.output(str != null ? str : "null");
            }
        };
        System.setOut(monitorPrintStream);
        System.setErr(monitorPrintStream);

        try {
            run(monitor);
        } catch (Throwable internalError) {
            internalError.printStackTrace(monitorPrintStream);
        } finally {
            monitor.close();
        }
    }

    private void run(final TargetMonitor monitor) {
        TestEnvironment testEnvironment = new TestEnvironment();
        testEnvironment.reset();

        String classOrPackageName;
        String qualification;

        // Check whether the class or package is qualified and, if so, strip it off and pass it
        // separately to the runners. For instance, may qualify a junit class by appending
        // #method_name, where method_name is the name of a single test of the class to run.
        int hash_position = qualifiedClassOrPackageName.indexOf("#");
        if (hash_position != -1) {
            classOrPackageName = qualifiedClassOrPackageName.substring(0, hash_position);
            qualification = qualifiedClassOrPackageName.substring(hash_position + 1);
        } else {
            classOrPackageName = qualifiedClassOrPackageName;
            qualification = null;
        }

        Set<Class<?>> classes = new ClassFinder().find(classOrPackageName);

        // if there is more than one class in the set, this must be a package. Since we're
        // running everything in the package already, remove any class called AllTests.
        if (classes.size() > 1) {
            Set<Class<?>> toRemove = new HashSet<>();
            for (Class<?> klass : classes) {
                if (klass.getName().endsWith(".AllTests")) {
                    toRemove.add(klass);
                }
            }
            classes.removeAll(toRemove);
        }


        Profiler profiler = null;
        if (profile) {
            try {
                profiler = Profiler.getInstance();
            } catch (Exception e) {
                System.out.println("Profiling is disabled: " + e);
            }
        }
        if (profiler != null) {
            profiler.setup(profileThreadGroup, profileDepth, profileInterval);
        }
        for (Class<?> klass : classes) {
            TargetRunner targetRunner;
            try {
                targetRunner = runnerFactory.newRunner(monitor, qualification, klass,
                        skipPastReference, testEnvironment, timeoutSeconds, profile, args);
            } catch (RuntimeException e) {
                monitor.outcomeStarted(klass.getName());
                e.printStackTrace();
                monitor.outcomeFinished(Result.ERROR);
                return;
            }

            if (targetRunner == null) {
                monitor.outcomeStarted(klass.getName());
                System.out.println("Skipping " + klass.getName()
                        + ": no associated runner class");
                monitor.outcomeFinished(Result.UNSUPPORTED);
                continue;
            }

            boolean completedNormally = targetRunner.run(profiler);
            if (!completedNormally) {
                return; // let the caller start another process
            }
        }
        if (profiler != null) {
            profiler.shutdown(profileFile);
        }

        monitor.completedNormally(true);
    }

    public static void main(String[] args) throws IOException {
        new TestRunner(loadProperties(), new ArrayList<>(Arrays.asList(args))).run();
        System.exit(0);
    }

    /**
     * A {@link RunnerFactory} that will traverse a list of {@link RunnerFactory} instances to find
     * one that can be used to run the code.
     */
    private static class CompositeRunnerFactory implements RunnerFactory {

        private final List<? extends RunnerFactory> runnerFactories;

        private CompositeRunnerFactory(List<RunnerFactory> factories) {
            this.runnerFactories = factories;
        }

        @Override @Nullable
        public TargetRunner newRunner(TargetMonitor monitor, String qualification,
                Class<?> klass, AtomicReference<String> skipPastReference,
                TestEnvironment testEnvironment, int timeoutSeconds, boolean profile, String[] args) {
            for (RunnerFactory runnerFactory : runnerFactories) {
                TargetRunner targetRunner = runnerFactory.newRunner(monitor, qualification, klass,
                        skipPastReference, testEnvironment, timeoutSeconds, profile, args);
                if (targetRunner != null) {
                    return targetRunner;
                }
            }

            return null;
        }
    }
}
