/**
 * Copyright (c) 2013-2015, The SeedStack authors <http://seedstack.org>
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 */
package org.seedstack.spring.internal;

import org.seedstack.seed.core.internal.application.ApplicationPlugin;
import io.nuun.kernel.api.Plugin;
import io.nuun.kernel.api.plugin.InitState;
import io.nuun.kernel.api.plugin.context.InitContext;
import io.nuun.kernel.api.plugin.request.ClasspathScanRequest;
import io.nuun.kernel.core.AbstractPlugin;
import io.nuun.kernel.spi.DependencyInjectionProvider;
import org.apache.commons.configuration.Configuration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

/**
 * This plugin provides Spring integration, converting any Spring bean defined in configured contexts in a named
 * Guice binding.
 *
 * @author adrien.lauer@mpsa.com
 * @author epo.jemba@ext.mpsa.com
 */
public class SpringPlugin extends AbstractPlugin {
    public static final String SPRING_PLUGIN_CONFIGURATION_PREFIX = "org.seedstack.spring";
    public static final String APPLICATION_CONTEXT_REGEX = ".*-context.xml$";

    private static final Logger LOGGER = LoggerFactory.getLogger(SpringPlugin.class);

    private final Set<String> applicationContextsPaths = new HashSet<String>();
    private ClassPathXmlApplicationContext globalApplicationContext;

    @Override
    public String name() {
        return "spring";
    }

    @Override
    public String pluginPackageRoot() {
        return "META-INF.spring";
    }

    @Override
    public InitState init(InitContext initContext) {
        ApplicationPlugin applicationPlugin = (ApplicationPlugin) initContext.pluginsRequired().iterator().next();
        Configuration springConfiguration = applicationPlugin.getApplication().getConfiguration().subset(SPRING_PLUGIN_CONFIGURATION_PREFIX);

        Map<String, Collection<String>> scannedApplicationContexts = initContext.mapResourcesByRegex();

        SeedConfigurationFactoryBean.configuration = applicationPlugin.getApplication().getConfiguration();

        boolean autodetect = springConfiguration.getBoolean("autodetect", true);
        for (String applicationContextPath : scannedApplicationContexts.get(APPLICATION_CONTEXT_REGEX)) {
            if (autodetect && applicationContextPath.startsWith("META-INF/spring")) {
                applicationContextsPaths.add(applicationContextPath);
                LOGGER.info("Autodetected spring context at " + applicationContextPath);
            }
        }

        if (springConfiguration.containsKey("contexts")) {
            String[] explicitContexts = springConfiguration.getStringArray("contexts");
            for (String explicitContext : explicitContexts) {
                applicationContextsPaths.add(explicitContext);
                LOGGER.info("Configured spring context at " + explicitContext);
            }
        } else if (springConfiguration.containsKey("context")) {
            String explicitContext = springConfiguration.getString("context");
            applicationContextsPaths.add(explicitContext);
            LOGGER.info("Configured spring context at " + explicitContext);
        }

        LOGGER.info("Initializing spring contexts " + applicationContextsPaths);
        globalApplicationContext = new ClassPathXmlApplicationContext(this.applicationContextsPaths.toArray(new String[this.applicationContextsPaths.size()]));
        return InitState.INITIALIZED;
    }

    @Override
    public void stop() {
        if (globalApplicationContext != null) {
            LOGGER.info("Closing spring contexts " + applicationContextsPaths);
            globalApplicationContext.close();
        }
    }

    @Override
    public Collection<Class<? extends Plugin>> requiredPlugins() {
        Collection<Class<? extends Plugin>> plugins = new ArrayList<Class<? extends Plugin>>();
        plugins.add(ApplicationPlugin.class);
        return plugins;
    }

    @Override
    public Collection<ClasspathScanRequest> classpathScanRequests() {
        return classpathScanRequestBuilder().resourcesRegex(APPLICATION_CONTEXT_REGEX).build();
    }

    @Override
    public Object nativeUnitModule() {
        return globalApplicationContext;
    }

    @Override
    public DependencyInjectionProvider dependencyInjectionProvider() {
        return new SpringDependencyInjectionProvider();
    }
}

@@ -330,104 +330,39 @@
 ort 
-org.seedstack.seed.core.internal.application.ApplicationPlugin;%0Aimport io.nuun.kernel.api.Plugin
+com.google.common.collect.Lists
 ;%0Aim
@@ -669,24 +669,96 @@
 figuration;%0A
+import org.seedstack.seed.core.spi.configuration.ConfigurationProvider;%0A
 import org.s
@@ -882,36 +882,8 @@
 t;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -1893,111 +1893,106 @@
     
-ApplicationPlugin applicationPlugin = (ApplicationPlugin) initContext.pluginsRequired().iterator().next
+Configuration configuration = initContext.dependency(ConfigurationProvider.class).getConfiguration
 ();%0A
@@ -2039,47 +2039,9 @@
 n = 
-applicationPlugin.getApplication().getC
+c
 onfi
@@ -2048,18 +2048,16 @@
 guration
-()
 .subset(
@@ -2256,47 +2256,9 @@
 n = 
-applicationPlugin.getApplication().getC
+c
 onfi
@@ -2265,18 +2265,16 @@
 guration
-()
 ;%0A%0A     
@@ -3940,31 +3940,16 @@
 %3CClass%3C?
- extends Plugin
 %3E%3E requi
@@ -3975,58 +3975,34 @@
     
-Collection%3CClass%3C? extends Plugin%3E%3E plugins = 
+return Lists.%3CClass%3C?%3E%3E
 new
- 
 Arra
@@ -4010,105 +4010,37 @@
 List
-%3CClass%3C? extends Plugin%3E%3E();%0A        plugins.add(ApplicationPlugin.class);%0A        return plugins
+(ConfigurationProvider.class)
 ;%0A  

Upgrade nuun