/*
    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.sling.installer.provider.installhook;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.jar.JarInputStream;
import java.util.jar.Manifest;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;

import org.apache.commons.lang.StringUtils;
import org.apache.jackrabbit.vault.fs.api.ProgressTrackerListener;
import org.apache.jackrabbit.vault.fs.io.Archive;
import org.apache.jackrabbit.vault.fs.io.Archive.Entry;
import org.apache.jackrabbit.vault.fs.io.ImportOptions;
import org.apache.jackrabbit.vault.packaging.InstallContext;
import org.apache.jackrabbit.vault.packaging.InstallHook;
import org.apache.jackrabbit.vault.packaging.PackageException;
import org.apache.jackrabbit.vault.packaging.PackageProperties;
import org.apache.jackrabbit.vault.packaging.VaultPackage;
import org.apache.sling.installer.api.InstallableResource;
import org.apache.sling.installer.api.OsgiInstaller;
import org.apache.sling.installer.api.event.InstallationListener;
import org.apache.sling.installer.api.info.InfoProvider;
import org.apache.sling.installer.api.info.InstallationState;
import org.apache.sling.installer.api.info.Resource;
import org.apache.sling.installer.api.info.ResourceGroup;
import org.apache.sling.installer.api.tasks.ResourceState;
import org.apache.sling.settings.SlingSettingsService;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleEvent;
import org.osgi.framework.BundleListener;
import org.osgi.framework.FrameworkUtil;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceEvent;
import org.osgi.framework.ServiceListener;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class OsgiInstallerHook implements InstallHook {

    private static final Logger LOG = LoggerFactory.getLogger(OsgiInstallerHook.class);

    private static final String PACKAGE_PROP_INSTALL_PATH_REGEX = "installPathRegex";
    private static final String PACKAGE_PROPERTY_MAX_WAIT_IN_SEC = "maxWaitForOsgiInstallerInSec";
    private static final String PACKAGE_PROPERTY_INSTALL_PRIORITY = "osgiInstallerPriority";
    private static final String PACKAGE_PROPERTY_WAIT_FOR_OSGI_EVENTS_QUIET_IN_SEC = "waitForOsgiEventsQuietInSec";

    public static final int DEFAULT_PRIORITY_INSTALL_HOOK = 2000;
    private static final int DEFAULT_MAX_WAIT_IN_SEC = 60;
    private static final int DEFAULT_WAIT_FOR_OSGI_EVENTS_QUIET_IN_SEC = 1;

    public static final String URL_SCHEME = "jcrinstall";
    public static final String CONFIG_SUFFIX = ".config";
    public static final String JAR_SUFFIX = ".jar";

    private static final String ENTITY_ID_PREFIX_BUNDLE = "bundle:";

    private static final String MANIFEST_BUNDLE_SYMBOLIC_NAME = "Bundle-SymbolicName";
    private static final String MANIFEST_BUNDLE_VERSION = "Bundle-Version";
    private static final String FOLDER_META_INF = "META-INF";

    static final String JCR_CONTENT = "jcr:content";
    static final String JCR_CONTENT_DATA = JCR_CONTENT + "/jcr:data";
    static final String JCR_LAST_MODIFIED = "jcr:lastModified";
    static final String JCR_CONTENT_LAST_MODIFIED = JCR_CONTENT + "/" + JCR_LAST_MODIFIED;

    public static final String DOT = ".";

    InstallHookLogger logger = new InstallHookLogger();

    @Override
    public void execute(InstallContext context) throws PackageException {

        VaultPackage vaultPackage = context.getPackage();
        PackageProperties packageProperties = vaultPackage.getProperties();
        String installPathRegex = packageProperties.getProperty(PACKAGE_PROP_INSTALL_PATH_REGEX);

        ServiceReference<OsgiInstaller> osgiInstallerServiceRef = null;
        ServiceReference<SlingSettingsService> slingSettingsServiceRef = null;
        ServiceRegistration<InstallationListener> hookInstallationListenerServiceRegistration = null;

        ServiceReference<InfoProvider> infoProviderServiceRef = null;

        try {
            switch (context.getPhase()) {
            case PREPARE:
                if (StringUtils.isBlank(installPathRegex)) {
                    throw new IllegalArgumentException(
                            "When using OSGi installer install hook for synchronous installation, the package property "
                                    + PACKAGE_PROP_INSTALL_PATH_REGEX + " has to be provided.");
                }
                break;
            case INSTALLED:
                ImportOptions options = context.getOptions();
                logger.setOptions(options);

                logger.log(getClass().getSimpleName() + " is active in " + vaultPackage.getId());

                List<BundleInPackage> bundleResources = new ArrayList<>();
                List<String> configResourcePaths = new ArrayList<>();
                Archive archive = vaultPackage.getArchive();

                infoProviderServiceRef = getBundleContext().getServiceReference(InfoProvider.class);
                InfoProvider infoProvider = (InfoProvider) getBundleContext().getService(infoProviderServiceRef);
                InstallationState installationState = infoProvider.getInstallationState();

                slingSettingsServiceRef = getBundleContext().getServiceReference(SlingSettingsService.class);
                SlingSettingsService slingSettingsService = (SlingSettingsService) getBundleContext().getService(slingSettingsServiceRef);
                Set<String> runModes = slingSettingsService.getRunModes();

                collectResources(archive, archive.getRoot(), "", bundleResources, configResourcePaths, installPathRegex,
                        runModes);

                logger.log("Bundles in package " + bundleResources);

                Session session = context.getSession();

                Map<String, InstallableResource> bundlesToInstallByUrl = getBundlesToInstall(bundleResources, session, installationState,
                        packageProperties);
                Map<String, InstallableResource> configsToInstallByUrl = getConfigsToInstall(configResourcePaths, session,
                        installationState, packageProperties);

                if (bundlesToInstallByUrl.isEmpty() && configsToInstallByUrl.isEmpty()) {
                    logger.log("No installable resources that are not installed yet found.");
                    return;
                }

                logger.log("Installing " + bundlesToInstallByUrl.size() + " bundles and "
                        + configsToInstallByUrl.size() + " configs");
                osgiInstallerServiceRef = getBundleContext().getServiceReference(OsgiInstaller.class);
                OsgiInstaller osgiInstaller = getBundleContext().getService(osgiInstallerServiceRef);

                OsgiInstallerListener hookInstallationListener = new OsgiInstallerListener(bundlesToInstallByUrl.keySet(),
                        configsToInstallByUrl.keySet());
                hookInstallationListenerServiceRegistration = getBundleContext()
                        .registerService(InstallationListener.class, hookInstallationListener, null);

                List<InstallableResource> resourcesToUpdate = new ArrayList<>();
                resourcesToUpdate.addAll(bundlesToInstallByUrl.values());
                resourcesToUpdate.addAll(configsToInstallByUrl.values());
                logger.log("Updating resources " + resourcesToUpdate);
                osgiInstaller.updateResources(URL_SCHEME, resourcesToUpdate.toArray(new InstallableResource[resourcesToUpdate.size()]),
                        null);

                int maxWaitForOsgiInstallerInSec = getNumericPackageProperty(packageProperties, PACKAGE_PROPERTY_MAX_WAIT_IN_SEC,
                        DEFAULT_MAX_WAIT_IN_SEC);

                long startTime = System.currentTimeMillis();
                int bundlesLeftToInstall = 0;
                int configsLeftToInstall = 0;
                while ((bundlesLeftToInstall = hookInstallationListener.bundlesLeftToInstall()) > 0
                        || (configsLeftToInstall = hookInstallationListener.configsLeftToInstall()) > 0) {
                    if ((System.currentTimeMillis() - startTime) > maxWaitForOsgiInstallerInSec * 1000) {
                        logger.log("Installable resources " + resourcesToUpdate
                                + " could not be installed even after waiting " + maxWaitForOsgiInstallerInSec + "sec");
                        break;
                    }
                    logger.log("Waiting for " + bundlesLeftToInstall + " bundles / " + configsLeftToInstall + " configs to be installed");
                    Thread.sleep(1000);
                }
                if (bundlesLeftToInstall == 0 && configsLeftToInstall == 0) {
                    logger.log("All " + bundlesToInstallByUrl.size() + " bundles / " + configsToInstallByUrl.size()
                            + " configs have been successfully installed");
                }

                int waitForOsgiEventsQuietInSec = getNumericPackageProperty(packageProperties,
                        PACKAGE_PROPERTY_WAIT_FOR_OSGI_EVENTS_QUIET_IN_SEC, DEFAULT_WAIT_FOR_OSGI_EVENTS_QUIET_IN_SEC);
                waitForServiceChanges(waitForOsgiEventsQuietInSec);

                break;
            default:
                break;
            }
        } catch (Exception e) {
            throw new PackageException("Could not execute install hook to for synchronous installation: " + e, e);
        } finally {
            if (osgiInstallerServiceRef != null) {
                getBundleContext().ungetService(osgiInstallerServiceRef);
            }
            if (slingSettingsServiceRef != null) {
                getBundleContext().ungetService(slingSettingsServiceRef);
            }
            if (infoProviderServiceRef != null) {
                getBundleContext().ungetService(infoProviderServiceRef);
            }

            if (hookInstallationListenerServiceRegistration != null) {
                hookInstallationListenerServiceRegistration.unregister();
            }
        }
    }

    private int getNumericPackageProperty(PackageProperties packageProperties, String propertyName, int defaultVal) {
        String strVal = packageProperties.getProperty(propertyName);
        int intVal = strVal != null ? Integer.parseInt(strVal) : defaultVal;
        return intVal;
    }

    private Map<String, InstallableResource> getBundlesToInstall(List<BundleInPackage> bundlesInPackage, Session session,
            InstallationState installationState, PackageProperties packageProperties) throws RepositoryException, IOException {
        Map<String, InstallableResource> installableResources = new HashMap<>();
        Iterator<BundleInPackage> bundlesIt = bundlesInPackage.iterator();
        while (bundlesIt.hasNext()) {
            BundleInPackage bundle = bundlesIt.next();

            List<Resource> currentInstallerBundleResources = getBundleResources(installationState, bundle.symbolicName);

            boolean needsInstallation = false;
            if (currentInstallerBundleResources.isEmpty()) {
                needsInstallation = true;
            } else if (currentInstallerBundleResources.size() == 1) {
                Resource resource = currentInstallerBundleResources.get(0);

                if (resource.getState() == ResourceState.INSTALLED) {
                    String currentlyActiveBundleVersion = resource.getVersion().toString();
                    if (!StringUtils.equals(currentlyActiveBundleVersion, bundle.version)) {
                        logger.log("Bundle " + bundle.symbolicName + " is installed with version "
                                + currentlyActiveBundleVersion + " but package contains version " + bundle.version);
                        needsInstallation = true;
                    } else {
                        logger.log("Bundle " + bundle.symbolicName + " is already installed with version "
                                + currentlyActiveBundleVersion + " that matches " + bundle.version + " as provided in package");
                    }
                } else {
                    logger.log("Bundle " + bundle.symbolicName + " is not in state INSTALLED but in " + resource.getState());
                    needsInstallation = true;
                }

            } else {
                logger.log("Bundle " + bundle.symbolicName + " exists with multiple installer resources");
                boolean installedBundleResourceFound = false;
                for (Resource resource : currentInstallerBundleResources) {
                    logger.log("Resource " + resource);
                    if (resource.getState() == ResourceState.INSTALLED
                            && StringUtils.equals(resource.getVersion().toString(), bundle.version)) {
                        installedBundleResourceFound = true;
                    }
                }
                if (!installedBundleResourceFound) {
                    needsInstallation = true;
                }

            }

            if (needsInstallation) {
                logger.log("Bundle " + bundle.symbolicName + " requires installation");
                Node node = session.getNode(bundle.path);
                InstallableResource installableResource = convert(node, bundle.path, packageProperties);
                String bundleUrl = URL_SCHEME + ":" + bundle.path;
                installableResources.put(bundleUrl, installableResource);
            }
        }
        return installableResources;
    }

    private List<Resource> getBundleResources(InstallationState installationState, String symbolicId) {

        List<Resource> bundleResources = new ArrayList<Resource>();

        List<ResourceGroup> allGroups = new ArrayList<ResourceGroup>();
        allGroups.addAll(installationState.getInstalledResources());
        allGroups.addAll(installationState.getActiveResources());
        for (ResourceGroup resourceGroup : allGroups) {
            List<Resource> resources = resourceGroup.getResources();
            for (Resource resource : resources) {
                if (StringUtils.equals(resource.getEntityId(), ENTITY_ID_PREFIX_BUNDLE + symbolicId)) {
                    bundleResources.add(resource);
                }
            }
        }
        return bundleResources;
    }

    private Map<String, InstallableResource> getConfigsToInstall(List<String> configResourcePaths, Session session,
            InstallationState installationState, PackageProperties packageProperties)
            throws IOException, InvalidSyntaxException, RepositoryException {
        Map<String, InstallableResource> configsToInstallByUrl = new HashMap<>();
        for (String configResourcePath : configResourcePaths) {
            boolean needsInstallation = false;

            String configUrl = URL_SCHEME + ":" + configResourcePath;
            boolean configFound = false;
            List<ResourceGroup> installedResources = installationState.getInstalledResources();
            for (ResourceGroup resourceGroup : installedResources) {
                for (Resource resource : resourceGroup.getResources()) {
                    if (StringUtils.equals(configUrl, resource.getURL())) {
                        configFound = true;
                        logger.log("Config " + configResourcePath + " is already installed");
                    }
                }
            }
            if (!configFound) {
                logger.log("Config " + configResourcePath + " has not been installed");
                needsInstallation = true;
            }

            if (needsInstallation) {

                Node node = session.getNode(configResourcePath);
                InstallableResource installableResource = convert(node, configResourcePath, packageProperties);

                configsToInstallByUrl.put(configUrl, installableResource);
            }
        }
        return configsToInstallByUrl;
    }

    void collectResources(Archive archive, Entry entry, String dirPath, List<BundleInPackage> bundleResources,
            List<String> configResources, String installPathRegex, Set<String> actualRunmodes) {
        String entryName = entry.getName();
        if (entryName.equals(FOLDER_META_INF)) {
            return;
        }

        String dirPathWithoutJcrRoot = StringUtils.substringAfter(dirPath, "/jcr_root");
        String entryPath = dirPathWithoutJcrRoot + entryName;
        String dirPathWithoutSlash = StringUtils.chomp(dirPathWithoutJcrRoot, "/");

        boolean runmodesMatch;
        if (dirPathWithoutSlash.contains(DOT)) {
            String[] bits = dirPathWithoutSlash.split("\\" + DOT, 2);
            List<String> runmodesOfResource = Arrays.asList(bits[1].split("\\" + DOT));
            Set<String> matchingRunmodes = new HashSet<String>(runmodesOfResource);
            matchingRunmodes.retainAll(actualRunmodes);
            LOG.debug("Entry with runmode(s): entryPath={} runmodesOfResource={} actualRunmodes={} matchingRunmodes={}",
                    entryPath, runmodesOfResource, actualRunmodes, matchingRunmodes);
            runmodesMatch = matchingRunmodes.size() == runmodesOfResource.size();
            if (!runmodesMatch) {
                logger.log("Skipping installation of  " + entryPath
                        + " because the path is not matching all actual runmodes " + actualRunmodes);
            }
        } else {
            runmodesMatch = true;
        }

        if (entryPath.matches(installPathRegex) && runmodesMatch) {

            if (entryName.endsWith(CONFIG_SUFFIX)) {
                configResources.add(entryPath);
            } else if (entryName.endsWith(JAR_SUFFIX)) {
                try (InputStream entryInputStream = archive.getInputSource(entry).getByteStream();
                        JarInputStream jarInputStream = new JarInputStream(entryInputStream)) {
                    Manifest manifest = jarInputStream.getManifest();
                    String symbolicName = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_SYMBOLIC_NAME);
                    String version = manifest.getMainAttributes().getValue(MANIFEST_BUNDLE_VERSION);

                    bundleResources.add(new BundleInPackage(entryPath, symbolicName, version));
                } catch (Exception e) {
                    throw new IllegalStateException(
                            "Could not read symbolic name and version from manifest of bundle " + entryName);
                }
            }

        }

        for (Entry child : entry.getChildren()) {
            collectResources(archive, child, dirPath + entryName + "/", bundleResources, configResources,
                    installPathRegex, actualRunmodes);
        }
    }

    InstallableResource convert(final Node node, final String path, PackageProperties packageProperties)
            throws IOException, RepositoryException {
        LOG.trace("Converting {} at path {}", node, path);
        final String digest = String.valueOf(node.getProperty(JCR_CONTENT_LAST_MODIFIED).getDate().getTimeInMillis());
        final InputStream is = node.getProperty(JCR_CONTENT_DATA).getStream();
        final Dictionary<String, Object> dict = new Hashtable<String, Object>();
        dict.put(InstallableResource.INSTALLATION_HINT, node.getParent().getName());
        int priority = getNumericPackageProperty(packageProperties, PACKAGE_PROPERTY_INSTALL_PRIORITY, DEFAULT_PRIORITY_INSTALL_HOOK);
        return new InstallableResource(path, is, dict, digest, null, priority);
    }

    private void waitForServiceChanges(int waitForOsgiEventsQuietInSec) {
        if (waitForOsgiEventsQuietInSec <= 0) {
            return;
        }
        InstallerHookOsgiEventListener osgiListener = new InstallerHookOsgiEventListener();
        BundleContext bundleContext = getBundleContext();
        bundleContext.addServiceListener(osgiListener);
        bundleContext.addBundleListener(osgiListener);

        long waitStart = System.currentTimeMillis();
        osgiListener.waitUntilQuiet(waitForOsgiEventsQuietInSec);
        logger.log("Waited " + (System.currentTimeMillis() - waitStart) + "ms in total for OSGi events to become quiet (for at least "
                + waitForOsgiEventsQuietInSec + "sec)");

        bundleContext.removeServiceListener(osgiListener);
        bundleContext.removeBundleListener(osgiListener);

    }

    // always get fresh bundle context to avoid "Dynamic class loader has already
    // been deactivated" exceptions
    private BundleContext getBundleContext() {
        // use the vault bundle to hook into the OSGi world
        Bundle currentBundle = FrameworkUtil.getBundle(InstallHook.class);
        if (currentBundle == null) {
            throw new IllegalStateException(
                    "The class " + InstallHook.class + " was not loaded through a bundle classloader");
        }
        BundleContext bundleContext = currentBundle.getBundleContext();
        if (bundleContext == null) {
            throw new IllegalStateException("Could not get bundle context for bundle " + currentBundle);
        }
        return bundleContext;
    }

    class BundleInPackage {
        final String path;
        final String symbolicName;
        final String version;

        public BundleInPackage(String path, String symbolicName, String version) {
            super();
            this.path = path;
            this.symbolicName = symbolicName;
            this.version = version;
        }

        @Override
        public String toString() {
            return "BundleInPackage [path=" + path + ", symbolicId=" + symbolicName + ", version=" + version + "]";
        }

    }

    static class InstallHookLogger {

        private ProgressTrackerListener listener;

        public void setOptions(ImportOptions options) {
            this.listener = options.getListener();
        }

        public void logError(Logger logger, String message, Throwable throwable) {
            if (listener != null) {
                listener.onMessage(ProgressTrackerListener.Mode.TEXT, "ERROR: " + message, "");
            }
            logger.error(message, throwable);
        }

        public void log(String message) {
            log(LOG, message);
        }

        public void log(Logger logger, String message) {
            if (listener != null) {
                listener.onMessage(ProgressTrackerListener.Mode.TEXT, message, "");
                logger.debug(message);
            } else {
                logger.info(message);
            }
        }
    }

    static class InstallerHookOsgiEventListener implements ServiceListener, BundleListener {

        private long lastEventTimestamp = System.currentTimeMillis();

        @Override
        public void serviceChanged(ServiceEvent event) {
            lastEventTimestamp = System.currentTimeMillis();
            LOG.trace("Service changed event {}", event);
        }

        @Override
        public void bundleChanged(BundleEvent event) {
            lastEventTimestamp = System.currentTimeMillis();
            LOG.trace("Bundle changed event {}", event);
        }

        public void waitUntilQuiet(long waitInSec) {
            try {
                while (System.currentTimeMillis() - lastEventTimestamp < waitInSec * 1000) {
                    Thread.sleep(100);
                }
            } catch (InterruptedException e) {
                LOG.warn("Wait for OSGi events was interrupted");
            }
        }
    }

}
