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

import org.apache.winegrower.deployer.OSGiBundleLifecycle;
import org.apache.winegrower.scanner.StandaloneScanner;
import org.apache.winegrower.scanner.manifest.HeaderManifestContributor;
import org.apache.winegrower.scanner.manifest.KarafCommandManifestContributor;
import org.apache.winegrower.scanner.manifest.ManifestContributor;
import org.apache.winegrower.scanner.manifest.OSGIInfContributor;
import org.apache.winegrower.scanner.manifest.OSGiCDIManifestContributor;
import org.apache.winegrower.scanner.manifest.RequirementManifestContributor;
import org.apache.winegrower.service.BundleRegistry;
import org.apache.winegrower.service.DefaultConfigurationAdmin;
import org.apache.winegrower.service.DefaultEventAdmin;
import org.apache.winegrower.service.OSGiServices;
import org.apache.winegrower.service.Slf4jOSGiLoggerFactory;
import org.osgi.framework.ServiceReference;
import org.osgi.service.cm.ConfigurationAdmin;
import org.osgi.service.cm.ConfigurationListener;
import org.osgi.service.event.EventAdmin;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.nio.file.FileVisitResult;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.SimpleFileVisitor;
import java.nio.file.attribute.BasicFileAttributes;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.ServiceLoader;
import java.util.UUID;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.Predicate;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;

import static java.util.Arrays.asList;
import static java.util.Collections.emptyList;
import static java.util.Locale.ROOT;
import static java.util.Optional.ofNullable;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

public interface Ripener extends AutoCloseable {
    Configuration getConfiguration();

    long getStartTime();

    Ripener start();

    void stop();

    OSGiServices getServices();

    BundleRegistry getRegistry();

    ConfigurationAdmin getConfigurationAdmin();

    EventAdmin getEventAdmin();

    @Override
    void close();

    class Configuration {
        private static final Collection<String> DEFAULT_EXCLUSIONS = asList(
                "slf4j-",
                "xbean-",
                "org.osgi.",
                "opentest4j-",
                "junit-platform-",
                "junit-jupiter-",
                "debugger-agent",
                "asm-"
        );

        private File workDir = new File(System.getProperty("java.io.tmpdir"), "karaf-boot_" + UUID.randomUUID().toString());
        private Predicate<String> jarFilter = it -> DEFAULT_EXCLUSIONS.stream().anyMatch(it::startsWith);
        private Collection<String> scanningIncludes;
        private Collection<String> scanningExcludes;
        private Collection<String> ignoredBundles = emptyList();
        private Collection<ManifestContributor> manifestContributors = Stream.concat(
                // built-in
                Stream.of(
                        new HeaderManifestContributor(), new RequirementManifestContributor(),
                        new OSGIInfContributor(),
                        new KarafCommandManifestContributor(),
                        new OSGiCDIManifestContributor()),
                // extensions
                StreamSupport.stream(ServiceLoader.load(ManifestContributor.class).spliterator(), false)
        ).collect(toList());
        // known bundles
        private List<String> prioritizedBundles = asList(
                "org.apache.aries.blueprint.core",
                "org.apache.aries.blueprint.cm",
                "pax-web-extender-whiteboard",
                "org.apache.aries.jax.rs.whiteboard",
                "pax-web-runtime",
                "org.apache.aries.cdi");

        public Collection<String> getIgnoredBundles() {
            return ignoredBundles;
        }

        public void setIgnoredBundles(final Collection<String> ignoredBundles) {
            this.ignoredBundles = ignoredBundles;
        }

        public List<String> getPrioritizedBundles() {
            return prioritizedBundles;
        }

        public void setPrioritizedBundles(final List<String> prioritizedBundles) {
            this.prioritizedBundles = prioritizedBundles;
        }

        public Collection<ManifestContributor> getManifestContributors() {
            return manifestContributors;
        }

        public void setManifestContributors(final Collection<ManifestContributor> manifestContributors) {
            this.manifestContributors = manifestContributors;
        }

        public Collection<String> getScanningIncludes() {
            return scanningIncludes;
        }

        public void setScanningIncludes(final Collection<String> scanningIncludes) {
            this.scanningIncludes = scanningIncludes;
        }

        public Collection<String> getScanningExcludes() {
            return scanningExcludes;
        }

        public void setScanningExcludes(final Collection<String> scanningExcludes) {
            this.scanningExcludes = scanningExcludes;
        }

        public File getWorkDir() {
            return workDir;
        }

        public void setWorkDir(final File workDir) {
            this.workDir = workDir;
        }

        public void setJarFilter(final Predicate<String> jarFilter) {
            this.jarFilter = jarFilter;
        }

        public Predicate<String> getJarFilter() {
            return jarFilter;
        }
    }


    class Impl implements Ripener {
        private static final Logger LOGGER = LoggerFactory.getLogger(Ripener.class);

        private final ConfigurationAdmin configurationAdmin;
        private final EventAdmin eventAdmin;
        private final OSGiServices services;
        private final BundleRegistry registry;

        private final Configuration configuration;

        private long startTime = -1;

        public Impl(final Configuration configuration) {
            this.configuration = configuration;

            final Collection<ConfigurationListener> configurationListeners = new ArrayList<>();
            final Collection<DefaultEventAdmin.EventHandlerInstance> eventListeners = new ArrayList<>();
            this.services = new OSGiServices(this, configurationListeners, eventListeners);
            this.registry = new BundleRegistry(services, configuration);

            this.configurationAdmin = loadConfigurationAdmin(configurationListeners);
            this.eventAdmin = loadEventAdmin(eventListeners);
            registerBuiltInService(ConfigurationAdmin.class, this.configurationAdmin, new Hashtable<>());
            registerBuiltInService(EventAdmin.class, this.eventAdmin, new Hashtable<>());
            registerBuiltInService(org.osgi.service.log.LoggerFactory.class, loadLoggerFactory(), new Hashtable<>());

            try (final InputStream stream = Thread.currentThread().getContextClassLoader().getResourceAsStream("winegrower.properties")) {
                loadConfiguration(stream);
            } catch (final IOException e) {
                LOGGER.warn(e.getMessage());
            }
        }

        public <T> void registerBuiltInService(final Class<T> type, final T impl, final Dictionary<String, Object> props) {
            if (Boolean.getBoolean("winegrower.builtin.services." + type.getName() + ".skip")) {
                return;
            }
            this.services.registerService(new String[]{type.getName()}, impl, props, this.registry.getBundles().get(0L).getBundle());
        }

        private ConfigurationAdmin loadConfigurationAdmin(final Collection<ConfigurationListener> configurationListeners) {
            final Iterator<ConfigurationAdmin> configurationAdminIterator = ServiceLoader.load(ConfigurationAdmin.class).iterator();
            if (configurationAdminIterator.hasNext()) {
                return configurationAdminIterator.next();
            }
            return new DefaultConfigurationAdmin(new HashMap<>(), configurationListeners) {
                @Override
                protected ServiceReference<ConfigurationAdmin> getSelfReference() {
                    return (ServiceReference<ConfigurationAdmin>) services.getServices().iterator().next().getReference();
                }
            };
        }

        private org.osgi.service.log.LoggerFactory loadLoggerFactory() {
            final Iterator<org.osgi.service.log.LoggerFactory> eventAdminIterator = ServiceLoader.load(org.osgi.service.log.LoggerFactory.class).iterator();
            if (eventAdminIterator.hasNext()) {
                return eventAdminIterator.next();
            }
            return new Slf4jOSGiLoggerFactory();
        }

        private EventAdmin loadEventAdmin(final Collection<DefaultEventAdmin.EventHandlerInstance> listeners) {
            final Iterator<EventAdmin> eventAdminIterator = ServiceLoader.load(EventAdmin.class).iterator();
            if (eventAdminIterator.hasNext()) {
                return eventAdminIterator.next();
            }
            return new DefaultEventAdmin(
                    listeners,
                    Integer.getInteger("winegrower.builtin.services." + EventAdmin.class.getName() + ".pool.core", Math.max(Runtime.getRuntime().availableProcessors(), 2)));
        }

        public void loadConfiguration(final InputStream stream) throws IOException {
            final Properties embedConfig = new Properties();
            if (stream != null) {
                embedConfig.load(stream);
                if (!embedConfig.isEmpty()) {
                    loadConfiguration(embedConfig);
                }
            }
        }

        // case insensitive
        public void loadConfiguration(final Properties embedConfig) {
            final Map<Object, Method> setters = Stream.of(this.configuration.getClass().getMethods())
                    .filter(it -> it.getName().startsWith("set") && it.getParameterCount() == 1)
                    .collect(toMap(it ->
                                    (Character.toLowerCase(it.getName().charAt(3)) + it.getName().substring(4)).toLowerCase(ROOT),
                            identity()));
            final Collection<String> matched = new ArrayList<>();
            embedConfig.stringPropertyNames().stream().filter(it -> setters.containsKey(it.toLowerCase(ROOT))).forEach(key -> {
                final String value = embedConfig.getProperty(key);
                if (value == null) {
                    return;
                }
                final String keyLowerCase = key.toLowerCase(ROOT);
                final Method setter = setters.get(keyLowerCase);
                matched.add(keyLowerCase);
                final Class<?> type = setter.getParameters()[0].getType();
                try {
                    if (type == String.class) {
                        setter.invoke(this.configuration, value);
                        return;
                    } else if (type == File.class) {
                        setter.invoke(this.configuration, new File(value));
                        return;
                    }

                    // from here all parameters are lists
                    final Collection<String> asList = Stream.of(value.split(","))
                            .map(String::trim)
                            .filter(it -> !it.isEmpty())
                            .collect(toList());
                    if (type == Predicate.class) { // Predicate<String> + startsWith logic
                        final Predicate<String> predicate =
                                val -> val != null && asList.stream().anyMatch(val::startsWith);
                        setter.invoke(this.configuration, predicate);
                    } else if (type == List.class) {
                        setter.invoke(this.configuration, asList);
                    } else if (type == Collection.class
                            && ManifestContributor.class == ParameterizedType.class.cast(
                            setter.getParameters()[0].getParameterizedType()).getActualTypeArguments()[0]) {
                        final ClassLoader loader = Thread.currentThread().getContextClassLoader();
                        setter.invoke(this.configuration, asList.stream()
                                .map(it -> {
                                    try {
                                        return loader.loadClass(it);
                                    } catch (final ClassNotFoundException e) {
                                        throw new IllegalArgumentException(e);
                                    }
                                })
                                .collect(toList()));
                    } else if (type == Collection.class) { // Collection<String>
                        setter.invoke(this.configuration, asList);
                    } else {
                        throw new IllegalArgumentException("Unsupported: " + setter);
                    }
                } catch (final IllegalAccessException e) {
                    throw new IllegalArgumentException(e);
                } catch (final InvocationTargetException e) {
                    throw new IllegalArgumentException(e.getTargetException());
                }
            });

            if (DefaultConfigurationAdmin.class.isInstance(configurationAdmin)) {
                final DefaultConfigurationAdmin dca = DefaultConfigurationAdmin.class.cast(configurationAdmin);
                embedConfig.stringPropertyNames()
                        .stream()
                        .filter(it -> it.startsWith("winegrower.service."))
                        .peek(matched::add)
                        .forEach(key -> dca.getProvidedConfiguration().put(key, embedConfig.getProperty(key)));
            }

            embedConfig.stringPropertyNames().stream().filter(it -> !matched.contains(it.toLowerCase(ROOT)))
                    .forEach(it -> LOGGER.warn("Didn't match configuration {}, did you mispell it?", it));
        }

        @Override
        public Configuration getConfiguration() {
            return configuration;
        }

        @Override
        public long getStartTime() {
            return startTime;
        }

        @Override
        public synchronized Ripener start() {
            startTime = System.currentTimeMillis();
            LOGGER.info("Starting Apache Winegrower application on {}",
                    LocalDateTime.ofInstant(Instant.ofEpochMilli(startTime), ZoneId.systemDefault()));
            final StandaloneScanner scanner = new StandaloneScanner(configuration, registry.getFramework());
            final AtomicLong bundleIdGenerator = new AtomicLong(1);
            Stream.concat(Stream.concat(
                    scanner.findOSGiBundles().stream(),
                    scanner.findPotentialOSGiBundles().stream()),
                    scanner.findEmbeddedClasses().stream())
                    .sorted(this::compareBundles)
                    .map(it -> new OSGiBundleLifecycle(
                            it.getManifest(), it.getJar(),
                            services, registry, configuration,
                            bundleIdGenerator.getAndIncrement(),
                            it.getFiles()))
                    .peek(OSGiBundleLifecycle::start)
                    .peek(it -> registry.getBundles().put(it.getBundle().getBundleId(), it))
                    .forEach(bundle -> LOGGER.debug("Bundle {}", bundle));
            return this;
        }

        @Override
        public synchronized void stop() {
            LOGGER.info("Stopping Apache Winegrower application on {}", LocalDateTime.now());
            final Map<Long, OSGiBundleLifecycle> bundles = registry.getBundles();
            bundles.values().stream()
                    .sorted((o1, o2) -> (int) (o2.getBundle().getBundleId() - o1.getBundle().getBundleId()))
                    .forEach(OSGiBundleLifecycle::stop);
            bundles.clear();
            if (configuration.getWorkDir().exists()) {
                try {
                    Files.walkFileTree(configuration.getWorkDir().toPath(), new SimpleFileVisitor<Path>() {
                        @Override
                        public FileVisitResult visitFile(final Path file, final BasicFileAttributes attrs) throws IOException {
                            Files.delete(file);
                            return super.visitFile(file, attrs);
                        }

                        @Override
                        public FileVisitResult postVisitDirectory(final Path dir, final IOException exc) throws IOException {
                            Files.delete(dir);
                            return super.postVisitDirectory(dir, exc);
                        }
                    });
                } catch (final IOException e) {
                    LOGGER.warn("Can't delete work directory", e);
                }
            }
            if (DefaultEventAdmin.class.isInstance(eventAdmin)) {
                DefaultEventAdmin.class.cast(eventAdmin).close();
            }
        }

        @Override
        public OSGiServices getServices() {
            return services;
        }

        @Override
        public BundleRegistry getRegistry() {
            return registry;
        }

        @Override
        public ConfigurationAdmin getConfigurationAdmin() {
            return configurationAdmin;
        }

        @Override
        public EventAdmin getEventAdmin() {
            return eventAdmin;
        }

        @Override // for try with resource syntax
        public void close() {
            stop();
        }

        private int compareBundles(final StandaloneScanner.BundleDefinition bundle1, final StandaloneScanner.BundleDefinition bundle2) {
            final String id1 = getBundleId(bundle1);
            final String id2 = getBundleId(bundle2);
            final int index1 = matchPriorities(id1);
            final int index2 = matchPriorities(id2);
            if (index1 == index2) {
                return id1.compareTo(id2);
            }
            if (index1 == -1) {
                return 1;
            }
            if (index2 == -1) {
                return -1;
            }
            return index1 - index2;
        }

        private String getBundleId(final StandaloneScanner.BundleDefinition bundle) {
            return ofNullable(bundle.getJar()).map(File::getName)
                    .orElseGet(() -> Stream.of("Bundle-SymbolicName", "Bundle-Name")
                            .map(k -> bundle.getManifest().getMainAttributes().getValue(k))
                            .findFirst()
                            .orElseGet(() -> Long.toString(System.identityHashCode(bundle))));
        }

        private int matchPriorities(final String name) {
            return configuration.getPrioritizedBundles().stream()
                    .filter(name::startsWith)
                    .findFirst()
                    .map(it -> configuration.getPrioritizedBundles().indexOf(it))
                    .orElse(-1);
        }
    }

    static Ripener create(final Configuration configuration) {
        // we can plug a SPI later on here if needed
        return new Impl(configuration);
    }

    static void main(final String[] args) {
        final CountDownLatch latch = new CountDownLatch(1);
        final Configuration configuration = new Configuration();
        ofNullable(System.getProperty("winegrower.ripener.configuration.workdir"))
                .map(String::valueOf)
                .map(File::new)
                .ifPresent(configuration::setWorkDir);
        ofNullable(System.getProperty("winegrower.ripener.configuration.prioritizedBundles"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .map(it -> asList(it.split(",")))
                .ifPresent(configuration::setPrioritizedBundles);
        ofNullable(System.getProperty("winegrower.ripener.configuration.ignoredBundles"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .map(it -> asList(it.split(",")))
                .ifPresent(configuration::setIgnoredBundles);
        ofNullable(System.getProperty("winegrower.ripener.configuration.scanningIncludes"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .map(it -> asList(it.split(",")))
                .ifPresent(configuration::setScanningIncludes);
        ofNullable(System.getProperty("winegrower.ripener.configuration.scanningExcludes"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .map(it -> asList(it.split(",")))
                .ifPresent(configuration::setScanningExcludes);
        ofNullable(System.getProperty("winegrower.ripener.configuration.manifestContributors"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .map(it -> asList(it.split(",")))
                .ifPresent(contributors -> {
                    configuration.setManifestContributors(contributors.stream().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(ManifestContributor.class::cast).collect(toList()));
                });
        ofNullable(System.getProperty("winegrower.ripener.configuration.jarFilter"))
                .map(String::valueOf)
                .filter(it -> !it.isEmpty())
                .ifPresent(filter -> {
                    try {
                        configuration.setJarFilter((Predicate<String>) Thread.currentThread().getContextClassLoader().loadClass(filter)
                                .getConstructor().newInstance());
                    } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException | ClassNotFoundException e) {
                        throw new IllegalArgumentException(e);
                    } catch (final InvocationTargetException e) {
                        throw new IllegalArgumentException(e.getTargetException());
                    }
                });
        final Ripener main = new Impl(configuration).start();
        Runtime.getRuntime().addShutdownHook(new Thread() {

            {
                setName(getClass().getName() + "-shutdown-hook");
            }

            @Override
            public void run() {
                main.stop();
                latch.countDown();
            }
        });
        try {
            latch.await();
        } catch (final InterruptedException e) {
            Thread.currentThread().interrupt();
        }
    }
}
