/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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 org.apache.struts2.osgi;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.FileManagerFactory;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.config.Configuration;
import com.opensymphony.xwork2.config.ConfigurationException;
import com.opensymphony.xwork2.config.PackageProvider;
import com.opensymphony.xwork2.config.entities.PackageConfig;
import com.opensymphony.xwork2.inject.Inject;
import com.opensymphony.xwork2.util.finder.ClassLoaderInterface;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.LogManager;
import org.apache.commons.lang3.StringUtils;
import org.apache.struts2.osgi.host.OsgiHost;
import org.apache.struts2.osgi.loaders.VelocityBundleResourceLoader;
import org.apache.struts2.views.velocity.VelocityManager;
import org.apache.velocity.app.Velocity;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;

import javax.servlet.ServletContext;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;

/**
 * Struts package provider that starts the OSGi container and deelgates package loading
 */
public class OsgiConfigurationProvider implements PackageProvider, BundleListener {

    private static final Logger LOG = LogManager.getLogger(OsgiConfigurationProvider.class);

    private Configuration configuration;
    private ObjectFactory objectFactory;
    private FileManagerFactory fileManagerFactory;

    private OsgiHost osgiHost;
    private BundleContext bundleContext;
    private BundleAccessor bundleAccessor;
    private boolean bundlesChanged = false;
    private ServletContext servletContext;

    public void init(Configuration configuration) throws ConfigurationException {
        osgiHost = (OsgiHost) servletContext.getAttribute(StrutsOsgiListener.OSGI_HOST);
        bundleContext = osgiHost.getBundleContext();
        bundleAccessor.setBundleContext(bundleContext);
        bundleAccessor.setOsgiHost(osgiHost);
        this.configuration = configuration;

        //this class loader interface can be used by other plugins to lookup resources
        //from the bundles. A temporary class loader interface is set during other configuration
        //loading as well
        servletContext.setAttribute(ClassLoaderInterface.CLASS_LOADER_INTERFACE, new BundleClassLoaderInterface());
    }

    public synchronized void loadPackages() throws ConfigurationException {
        if (LOG.isTraceEnabled())
            LOG.trace("Loading packages from XML and Convention on startup");                

        //init action context
        if (ActionContext.getContext() == null) {
            createActionContext();
        }

        Set<String> bundleNames = new HashSet<>();

        //iterate over the bundles and load packages from them
        for (Bundle bundle : osgiHost.getBundles().values()) {
            String bundleName = bundle.getSymbolicName();
            if (shouldProcessBundle(bundle) && !bundleNames.contains(bundleName)) {
                bundleNames.add(bundleName);
                //load XML and Convention config
                loadConfigFromBundle(bundle);
            }
        }

        bundlesChanged = false;
        bundleContext.addBundleListener(this);
    }

    protected ActionContext createActionContext() {
        return ActionContext.of(new HashMap<>()).bind();
    }

    /**
     * Loads XML config as well as Convention config from a bundle
     * Limitation: Constants and Beans are ignored on XML config
     *
     * @param bundle the bundle
     */
    protected void loadConfigFromBundle(Bundle bundle) {
        String bundleName = bundle.getSymbolicName();
        LOG.debug("Loading packages from bundle [{}]", bundleName);

        //init action context
        ActionContext ctx = ActionContext.getContext();
        if (ctx == null) {
            ctx = createActionContext();
        }

        try {
            //the Convention plugin will use BundleClassLoaderInterface from the ActionContext to find resources
            //and load classes
            ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, new BundleClassLoaderInterface());
            ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, bundleName);

            LOG.trace("Loading XML config from bundle [{}]", bundleName);

            //XML config
            PackageLoader loader = new BundlePackageLoader();
            for (PackageConfig pkg : loader.loadPackages(bundle, bundleContext, objectFactory, fileManagerFactory, configuration.getPackageConfigs())) {
                configuration.addPackageConfig(pkg.getName(), pkg);
                bundleAccessor.addPackageFromBundle(bundle, pkg.getName());
            }

            //Convention
            //get the existing packages before reloading the provider (se we can figure out what are the new packages)
            Set<String> packagesBeforeLoading = new HashSet<>(configuration.getPackageConfigNames());

            PackageProvider conventionPackageProvider = configuration.getContainer().getInstance(PackageProvider.class, "convention.packageProvider");
            if (conventionPackageProvider != null) {
                LOG.trace("Loading Convention config from bundle [{}]", bundleName);
                conventionPackageProvider.loadPackages();
            }

            Set<String> packagesAfterLoading = new HashSet<String>(configuration.getPackageConfigNames());
            packagesAfterLoading.removeAll(packagesBeforeLoading);
            if (!packagesAfterLoading.isEmpty()) {
                //add the new packages to the map of bundle -> package
                for (String packageName : packagesAfterLoading)
                    bundleAccessor.addPackageFromBundle(bundle, packageName);
            }

            if (this.configuration.getRuntimeConfiguration() != null) {
                //if there is a runtime config, it meas that this method was called froma bundle start event
                //instead of the initial load, in that case, reload the config
                this.configuration.rebuildRuntimeConfiguration();
            }
        } finally {
            ctx.put(BundleAccessor.CURRENT_BUNDLE_NAME, null);
            ctx.put(ClassLoaderInterface.CLASS_LOADER_INTERFACE, null);
        }
    }

    /**
     * Checks for "Struts2-Enabled" header in the bundle
     *
     * @param bundle the bundle
     *
     * @return true is struts2 enabled
     */
    protected boolean shouldProcessBundle(Bundle bundle) {
        // Cast to String is required on JDK7
        String strutsEnabled = (String) bundle.getHeaders().get(OsgiHost.OSGI_HEADER_STRUTS_ENABLED);

        return "true".equalsIgnoreCase(strutsEnabled);
    }

    public synchronized boolean needsReload() {
        return bundlesChanged;
    }

    @Inject
    public void setObjectFactory(ObjectFactory factory) {
        this.objectFactory = factory;
    }

    @Inject
    public void setBundleAccessor(BundleAccessor acc) {
        this.bundleAccessor = acc;
    }

    @Inject
    public void setVelocityManager(VelocityManager vm) {
        Properties props = new Properties();
        props.setProperty("osgi.resource.loader.description", "OSGI bundle loader");
        props.setProperty("osgi.resource.loader.class", VelocityBundleResourceLoader.class.getName());
        props.setProperty(Velocity.RESOURCE_LOADER, "strutsfile,strutsclass,osgi");
        vm.setVelocityProperties(props);
    }

    @Inject
    public void setServletContext(ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    @Inject
    public void setFileManagerFactory(FileManagerFactory fmFactory) {
        this.fileManagerFactory = fmFactory;
    }

    public void destroy() {
        try {
            osgiHost.destroy();
        } catch (Exception e) {
            if (LOG.isErrorEnabled()) {
                LOG.error("Failed to stop OSGi container", e);
            }
        }
    }

    /**
     * Listens to bundle event to load/unload config
     *
     * @param bundleEvent the bundle event
     */
    public void bundleChanged(BundleEvent bundleEvent) {
        Bundle bundle = bundleEvent.getBundle();
        String bundleName = bundle.getSymbolicName();
        if (bundleName != null && shouldProcessBundle(bundle)) {
            switch (bundleEvent.getType()) {
                case BundleEvent.STARTED:
                    LOG.trace("The bundle [{}] has been activated and will be scanned for struts configuration", bundleName);
                    loadConfigFromBundle(bundle);
                    break;
                case BundleEvent.STOPPED:
                    onBundleStopped(bundle);
                    break;
            }
        }
    }

    /**
     * This method is called when a bundle is stopped, so the config that is related to it is removed
     *
     * @param bundle the bundle that stopped
     */
    protected void onBundleStopped(Bundle bundle) {
        Set<String> packages = bundleAccessor.getPackagesByBundle(bundle);
        if (!packages.isEmpty()) {
            if (LOG.isTraceEnabled()) {
                LOG.trace("The bundle [{}] has been stopped. The packages [{}] will be disabled", bundle.getSymbolicName(), StringUtils.join(packages, ","));
            }
            for (String packageName : packages) {
                configuration.removePackageConfig(packageName);
            }
        }
    }

}
