/**
 * 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.scanner;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Collections.list;
import static java.util.Collections.singletonList;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static org.apache.xbean.finder.archive.ClasspathArchive.archive;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Properties;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.stream.Stream;

import org.apache.winegrower.Ripener;
import org.apache.winegrower.scanner.manifest.ManifestContributor;
import org.apache.winegrower.scanner.manifest.ManifestCreator;
import org.apache.xbean.finder.AnnotationFinder;
import org.apache.xbean.finder.ClassLoaders;
import org.apache.xbean.finder.UrlSet;
import org.apache.xbean.finder.archive.Archive;
import org.apache.xbean.finder.archive.ClassesArchive;
import org.apache.xbean.finder.util.Files;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class StandaloneScanner {
    private final static Logger LOGGER = LoggerFactory.getLogger(StandaloneScanner.class);
    private static final Attributes.Name OSGI_MANIFEST_MARKER = new Attributes.Name("Bundle-Version");

    private final List<URL> urls;
    private final Ripener.Configuration configuration;
    private final ClassLoader loader;
    private final File frameworkJar;
    private final Map<String, Manifest> providedManifests;
    private final Map<String, List<String>> providedIndex;

    public StandaloneScanner(final Ripener.Configuration configuration, final File frameworkJar) {
        this.configuration = configuration;
        this.frameworkJar = frameworkJar;
        this.loader = Thread.currentThread().getContextClassLoader();
        this.urls = findUrls();

        try { // fatjar plugin
            providedManifests = list(this.loader.getResources("WINEGROWER-INF/manifests.properties")).stream()
                .flatMap(url -> {
                    final Properties properties = new Properties();
                    try (final InputStream stream = url.openStream()) {
                        properties.load(stream);
                    } catch (final IOException e) {
                        throw new IllegalArgumentException(e);
                    }
                    return properties.stringPropertyNames().stream()
                            .collect(toMap(identity(), key -> {
                                final String property = properties.getProperty(key);
                                final Manifest manifest = new Manifest();
                                try (final ByteArrayInputStream mfStream = new ByteArrayInputStream(property.getBytes(StandardCharsets.UTF_8))) {
                                    manifest.read(mfStream);
                                } catch (final IOException e) {
                                    throw new IllegalArgumentException(e);
                                }
                                return manifest;
                            })).entrySet().stream();
                })
                .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
            providedIndex = list(this.loader.getResources("WINEGROWER-INF/index.properties")).stream()
                    .flatMap(url -> {
                        final Properties properties = new Properties();
                        try (final InputStream stream = url.openStream()) {
                            properties.load(stream);
                        } catch (final IOException e) {
                            throw new IllegalArgumentException(e);
                        }
                        return properties.stringPropertyNames().stream()
                                .collect(toMap(identity(), key -> {
                                    final String property = properties.getProperty(key);
                                    return asList(property.split(","));
                                })).entrySet().stream();
                    })
                    .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
        } catch (final IOException e) {
            throw new IllegalArgumentException(e);
        }
    }

    private List<URL> findUrls() {
        if (loader == null || System.getProperty("java.home") == null /*graalvm*/ ||
                Boolean.getBoolean("winegrower.scanner.standalone.skipUrlsScanning")) {
            return emptyList();
        }
        try {
            return new UrlSet(ClassLoaders.findUrls(loader)).excludeJvm().getUrls();
        } catch (final IOException e) {
            throw new IllegalStateException(e);
        }
    }

    public Collection<BundleDefinition> findEmbeddedClasses() {
        // potentially other scripting languages
        return scanGroovy();
    }

    private Collection<BundleDefinition> scanGroovy() {
        if (loader == null || !loader.getClass().getName().equals("groovy.lang.GroovyClassLoader")) {
            return emptyList();
        }
        try { // groovy - note that the classloader returns classes but not .class as resource so we fail to activate our contributors
            final Class<?>[] loadedClasses = Class[].class.cast(
                    loader.getClass().getMethod("getLoadedClasses").invoke(loader));
            try {
                final Archive archive = new ClassesArchive(loadedClasses);
                final Manifest groovyClassesManifest = tryLoadManifest(archive, "EmbeddedGroovyClasses");
                if (groovyClassesManifest == null) {
                    return emptyList();
                }
                LOGGER.debug("EmbeddedGroovyClasses was scanned and is converted to a bundle");
                return singletonList(new BundleDefinition(groovyClassesManifest, null, emptyList()));
            } catch (final LinkageError e) {
                LOGGER.debug("EmbeddedGroovyClasses is not scannable, maybe exclude it in framework configuration");
                return emptyList();
            }
        } catch (final Exception e) {
            return emptyList();
        }
    }

    public Collection<BundleDefinition> findPotentialOSGiBundles() {
        final KnownJarsFilter filter = new KnownJarsFilter(configuration);
        return urls.stream()
              .map(it -> new FileAndUrl(Files.toFile(it), it))
              .filter(it -> !it.file.getAbsoluteFile().equals(frameworkJar))
              .filter(it -> filter.test(it.file.getName()))
              .filter(it -> toDefinition(it.file) == null)
              .map(it -> {
                  final Archive jarArchive = archive(loader, it.url);
                  // we scan per archive to be able to create bundle after
                  try {
                      final String name = it.file.getName();
                      final Manifest manifest = tryLoadManifest(jarArchive, name);
                      if (manifest == null) {
                          return null;
                      }
                      LOGGER.debug("{} was scanned and is converted to a bundle", it.file);
                      return new BundleDefinition(manifest, it.file, null);
                  } catch (final LinkageError e) {
                      LOGGER.debug("{} is not scannable, maybe exclude it in framework configuration", it.file);
                      return null;
                  }
              })
              .filter(Objects::nonNull)
              .collect(toList());
    }

    public Collection<BundleDefinition> findOSGiBundles() {
        return Stream.concat(
                    urls.stream()
                        .map(Files::toFile)
                        .filter(this::isIncluded)
                        .filter(file -> !providedManifests.containsKey(file.getName())) // don't duplicate it
                        .filter(it -> this.configuration.getIgnoredBundles().stream().noneMatch(ex -> it.getName().startsWith(ex)))
                        .map(this::toDefinition)
                        .filter(Objects::nonNull),
                    providedManifests.entrySet().stream()
                        .map(it -> new BundleDefinition(it.getValue(), null, providedIndex.get(it.getKey()))))
                .collect(toList());
    }

    private Manifest tryLoadManifest(final Archive archive, final String name) {
        final AnnotationFinder archiveFinder = new ManifestContributor.WinegrowerAnnotationFinder(archive, false);
        final ManifestCreator manifestCreator = new ManifestCreator(name);
        configuration.getManifestContributors()
                .forEach(c -> c.contribute(archiveFinder, manifestCreator));
        final Manifest manifest = manifestCreator.getManifest();
        if (manifest == null) {
            LOGGER.debug("{} was scanned for nothing, maybe adjust scanning exclusions", name);
            return null;
        }
        return manifest;
    }

    private boolean isIncluded(final File file) {
        return !configuration.getJarFilter().test(file.getName());
    }

    private BundleDefinition toDefinition(final File file) {
        if (file.isDirectory()) {
            final File manifest = new File(file, "META-INF/MANIFEST.MF");
            if (manifest.exists()) {
                try (final InputStream stream = new FileInputStream(manifest)) {
                    final Manifest mf = new Manifest(stream);
                    if (isOSGi(mf)) {
                        return new BundleDefinition(mf, file, null);
                    }
                    return null;
                } catch (final IOException e) {
                    throw new IllegalStateException(e);
                }
            }
            return null;
        }
        try (final JarFile jar = new JarFile(file)) {
            final Manifest manifest = jar.getManifest();
            if (manifest == null) {
                return null;
            }
            if (isOSGi(manifest)) {
                return new BundleDefinition(manifest, file, null);
            }
            return null;
        } catch (final Exception e) {
            return null;
        }
    }

    private boolean isOSGi(final Manifest mf) {
        return mf.getMainAttributes().containsKey(OSGI_MANIFEST_MARKER);
    }

    public static class BundleDefinition {
        private final Manifest manifest;
        private final File jar;
        private final Collection<String> files;

        private BundleDefinition(final Manifest manifest, final File jar, final Collection<String> files) {
            this.manifest = manifest;
            this.jar = jar;
            this.files = files;
        }

        public Collection<String> getFiles() {
            return files;
        }

        public Manifest getManifest() {
            return manifest;
        }

        public File getJar() {
            return jar;
        }
    }

    private static class FileAndUrl {
        private final File file;
        private final URL url;

        private FileAndUrl(final File file, final URL url) {
            this.file = file;
            this.url = url;
        }
    }
}
