/**
 * 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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 org.apache.winegrower.extension.build.maven;

import org.apache.maven.artifact.Artifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.apache.xbean.finder.util.Files;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CountDownLatch;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.stream.Stream;

import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;
import static org.apache.maven.plugins.annotations.ResolutionScope.RUNTIME_PLUS_SYSTEM;

@Mojo(name = "pour", requiresDependencyResolution = RUNTIME_PLUS_SYSTEM)
public class PourMojo extends LibsMojo {

    @Parameter(property = "winegrower.workDir", defaultValue = "${project.build.directory}/winegrower/workdir")
    private File workDir;

    @Parameter(property = "winegrower.jarFilter")
    private String jarFilter;

    @Parameter(property = "winegrower.scanningIncludes")
    private Collection<String> scanningIncludes;

    @Parameter(property = "winegrower.scanningExcludes")
    private Collection<String> scanningExcludes;

    @Parameter(property = "winegrower.ignoredBundles")
    private Collection<String> ignoredBundles;

    @Parameter(property = "winegrower.manifestContributors")
    private Collection<String> manifestContributors;

    @Parameter(property = "winegrower.dependencyScopes", defaultValue = "provided,compile,system,runtime")
    private Collection<String> dependencyScopes;

    @Parameter(property = "winegrower.prioritizedBundles")
    private List<String> prioritizedBundles;

    @Parameter(property = "winegrower.systemVariables")
    private Map<String, String> systemVariables;

    @Parameter(property = "winegrower.waitOnSystemIn", defaultValue = "true")
    private boolean waitOnSystemIn; // if you use the shell this breaks it if set to true

    @Parameter(defaultValue = "${project}", readonly = true, required = true)
    private MavenProject project;

    @Override
    public void execute() throws MojoExecutionException {
        final Thread thread = Thread.currentThread();
        final ClassLoader loader = thread.getContextClassLoader();
        final ClassLoader appLoader = createClassLoader(loader);
        thread.setContextClassLoader(appLoader);
        try {
            final Consumer<Runnable> waitOnExit = defaultImpl -> {
                if (waitOnSystemIn) {
                    defaultImpl.run();
                } else { // just block
                    try {
                        new CountDownLatch(1).await();
                    } catch (final InterruptedException e) {
                        Thread.currentThread()
                                .interrupt();
                    }
                }
            };
            final Class<?> runClass = appLoader.loadClass("org.apache.winegrower.extension.build.common.Run");
            final Class<?> confClass = appLoader.loadClass("org.apache.winegrower.Ripener$Configuration");
            Runnable.class.cast(runClass.getConstructor(confClass, Map.class, Consumer.class)
                    .newInstance(createConfiguration(confClass), systemVariables, waitOnExit)).run();
        } catch (final Exception e) {
            throw new MojoExecutionException(e.getMessage(), e);
        } finally {
            if (appLoader != loader) {
                try {
                    URLClassLoader.class.cast(appLoader).close();
                } catch (final IOException e) {
                    getLog().warn(e.getMessage(), e);
                }
            }
            thread.setContextClassLoader(loader);
        }
    }

    private ClassLoader createClassLoader(final ClassLoader parent) {
        final List<File> jars = Stream.concat(
                collectLibs(),
                Stream.concat(project.getArtifacts().stream()
                                .filter(a -> !((dependencyScopes == null && !(Artifact.SCOPE_COMPILE.equals(
                                        a.getScope()) || Artifact.SCOPE_RUNTIME.equals(
                                        a.getScope()))) || (dependencyScopes != null && !dependencyScopes.contains(
                                        a.getScope()))))
                                .map(Artifact::getFile),
                        Stream.of(project.getBuild().getOutputDirectory()).map(File::new).filter(File::exists)))
                .collect(toList());
        final List<URL> urls = jars.stream().map(file -> {
            try {
                return file.toURI().toURL();
            } catch (final MalformedURLException e) {
                throw new IllegalArgumentException(e);
            }
        }).collect(toList());
        if (getLog().isDebugEnabled()) {
            getLog().debug("Startup classpath: " + jars);
        }
        final boolean excludeOsgi = jars.stream()
                .anyMatch(it -> it.getName().startsWith("org.osgi.") || it.getName().startsWith("osgi."));
        final boolean hasWinegrower = jars.stream()
                .anyMatch(it -> it.getName().startsWith("winegrower-core"));
        if (excludeOsgi) {
            // add build-common
            final File buildCommon = Files.toFile(parent.getResource("org/apache/winegrower/extension/build/common/Run.class"));
            try {
                urls.add(buildCommon.toURI().toURL());
            } catch (final MalformedURLException e) {
                throw new IllegalArgumentException(e);
            }
        }
        final ClassLoader workaroundMaven = new WorkAroundMavenClassLoader(parent);
        final ClassLoader parentLoader = !excludeOsgi || !hasWinegrower ? workaroundMaven : new IgnoreWinegrowerckClassLoader(workaroundMaven);
        return urls.isEmpty() ? workaroundMaven : new URLClassLoader(urls.toArray(new URL[0]), parentLoader) {
            @Override
            public boolean equals(final Object obj) {
                return super.equals(obj) || parent.equals(obj);
            }
        };
    }

    private Object createConfiguration(final Class<?> configClass)
            throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        final Object configuration = configClass.getConstructor().newInstance();
        ofNullable(workDir)
                .ifPresent(value -> doCall(configuration, "setWorkDir", new Class<?>[]{File.class}, new Object[]{value}));
        ofNullable(prioritizedBundles)
                .filter(it -> !it.isEmpty())
                .map(it -> it.stream().filter(v -> !"empty".equals(v)).collect(toList()))
                .ifPresent(value -> doCall(configuration, "setPrioritizedBundles", new Class<?>[]{List.class}, new Object[]{value}));
        ofNullable(ignoredBundles)
                .ifPresent(value -> doCall(configuration, "setIgnoredBundles", new Class<?>[]{Collection.class}, new Object[]{value}));
        ofNullable(scanningIncludes)
                .ifPresent(value -> doCall(configuration, "setScanningIncludes", new Class<?>[]{Collection.class}, new Object[]{value}));
        ofNullable(scanningExcludes)
                .ifPresent(value -> doCall(configuration, "setScanningExcludes", new Class<?>[]{Collection.class}, new Object[]{value}));
        ofNullable(manifestContributors)
                .filter(it -> !it.isEmpty())
                .ifPresent(contributors -> {
                    try {
                        final Class<?> type = Thread.currentThread().getContextClassLoader().loadClass(
                                "org.apache.winegrower.scanner.manifest.ManifestContributor");
                        final Collection<?> value = contributors.stream()
                                .filter(it -> !"empty".equals(it))
                                .map(clazz -> {
                                    try {
                                        return Thread.currentThread()
                                                .getContextClassLoader()
                                                .loadClass(clazz)
                                                .getConstructor()
                                                .newInstance();
                                    } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
                                        throw new IllegalArgumentException(e);
                                    } catch (final InvocationTargetException e) {
                                        throw new IllegalArgumentException(
                                                e.getTargetException());
                                    }
                                })
                                .map(type::cast)
                                .collect(toList());
                        doCall(configuration, "setManifestContributors", new Class<?>[]{Collection.class}, new Object[]{value});
                    } catch (final ClassNotFoundException e) {
                        throw new IllegalArgumentException(e);
                    }
                });
        ofNullable(jarFilter)
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .ifPresent(filter -> {
                    try {
                        final Predicate<String> predicate = (Predicate<String>) Thread.currentThread()
                                .getContextClassLoader().loadClass(filter).getConstructor().newInstance();
                        doCall(configuration, "setJarFilter", new Class<?>[]{Predicate.class}, new Object[]{predicate});
                    } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
                        throw new IllegalArgumentException(e);
                    } catch (final InvocationTargetException e) {
                        throw new IllegalArgumentException(e.getTargetException());
                    }
                });
        return configuration;
    }

    private static void doCall(final Object instance, final String mtd, final Class<?>[] paramTypes, final Object[] args) {
        try {
            instance.getClass().getMethod(mtd, paramTypes).invoke(instance, args);
        } catch (final InvocationTargetException ite) {
            final Throwable targetException = ite.getTargetException();
            if (RuntimeException.class.isInstance(targetException)) {
                throw RuntimeException.class.cast(targetException);
            }
            throw new IllegalStateException(targetException);
        } catch (final Exception ex) {
            if (RuntimeException.class.isInstance(ex)) {
                throw RuntimeException.class.cast(ex);
            }
            throw new IllegalStateException(ex);
        }
    }

    private static class WorkAroundMavenClassLoader extends ClassLoader {
        private WorkAroundMavenClassLoader(final ClassLoader parent) {
            super(parent);
        }

        @Override
        public Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
            if (name.startsWith("javax.")) {
                final String sub = name.substring("javax.".length());
                if (sub.startsWith("enterprise.") || sub.startsWith("decorator.")) { // maven has an outdated cdi-api
                    throw new ClassNotFoundException(name);
                }
            }
            return getParent().loadClass(name);
        }
    }

    private static class IgnoreWinegrowerckClassLoader extends ClassLoader {
        private IgnoreWinegrowerckClassLoader(final ClassLoader workaroundMaven) {
            super(workaroundMaven);
        }

        @Override
        protected Class<?> loadClass(final String name, final boolean resolve) throws ClassNotFoundException {
            if (name.startsWith("org.")) {
                final String sub = name.substring("org.".length());
                if (sub.startsWith("osgi.")) {
                    throw new ClassNotFoundException(name);
                } else if (sub.startsWith("apache.")) {
                    final String apache = sub.substring("apache.".length());
                    if (apache.startsWith("winegrower.")) {
                        throw new ClassNotFoundException(name);
                    }
                    if (apache.startsWith("xbean.")) {
                        throw new ClassNotFoundException(name);
                    }
                }
            }
            return super.loadClass(name, resolve);
        }
    }
}
