/*
 * 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.jcr.contentloader.internal;

import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;

import javax.jcr.Node;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.lock.LockException;

import org.apache.sling.commons.mime.MimeTypeService;
import org.apache.sling.jcr.api.SlingRepository;
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.Constants;
import org.osgi.framework.SynchronousBundleListener;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>ContentLoaderService</code> is the service
 * providing the following functionality:
 * <ul>
 * <li>Bundle listener to load and unload initial content.
 * </ul>
 *
 */
@Component(service = {},
    property = {
            Constants.SERVICE_VENDOR + "=The Apache Software Foundation",
            Constants.SERVICE_DESCRIPTION + "=Apache Sling Content Loader Implementation"
    })
public class ContentLoaderService implements SynchronousBundleListener, BundleHelper {

    public static final String PROPERTY_CONTENT_LOADED = "content-loaded";
    public static final String PROPERTY_CONTENT_LOADED_AT = "content-load-time";
    private static final String PROPERTY_CONTENT_LOADED_BY = "content-loaded-by";
    private static final String PROPERTY_CONTENT_UNLOADED_AT = "content-unload-time";
    private static final String PROPERTY_CONTENT_UNLOADED_BY = "content-unloaded-by";
    public static final String PROPERTY_UNINSTALL_PATHS = "uninstall-paths";

    public static final String BUNDLE_CONTENT_NODE = "/var/sling/bundle-content";

    /** default log */
    final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * The JCR Repository we access to resolve resources
     */
    @Reference
    private SlingRepository repository;

    /**
     * The MimeTypeService used by the bundle content loader to
     * resolve MIME types for files to be installed.
     */
    @Reference
    private MimeTypeService mimeTypeService;

    /**
     * Service storing all available content readers.
     */
    @Reference
    private ContentReaderWhiteboard contentReaderWhiteboard;

    /**
     * The initial content loader which is called to load initial content up
     * into the repository when the providing bundle is installed.
     */
    private BundleContentLoader bundleContentLoader;

    /**
     * The id of the current instance
     */
    private String slingId;

    /**
     * List of currently updated bundles.
     */
    private final Set<String> updatedBundles = new HashSet<>();

    /** Sling settings service. */
    @Reference
    protected SlingSettingsService settingsService;

    // ---------- BundleListener -----------------------------------------------

    /**
     * Loads and unloads any content provided by the bundle whose state
     * changed. If the bundle has been started, the content is loaded. If
     * the bundle is about to stop, the content are unloaded.
     *
     * @param event The <code>BundleEvent</code> representing the bundle state
     *            change.
     */
    @Override
    public synchronized void bundleChanged(BundleEvent event) {

        //
        // NOTE:
        // This is synchronous - take care to not block the system !!
        //

        if (this.bundleContentLoader == null) {
            return;
        }

        Session session = null;
        final Bundle bundle = event.getBundle();
        switch (event.getType()) {
            case BundleEvent.RESOLVED:
                // register content when the bundle content is available
                // as node types are registered when the bundle is installed
                // we can safely add the content at this point.
                try {
                    session = this.getSession();
                    final boolean isUpdate;
                    isUpdate = this.updatedBundles.remove(bundle.getSymbolicName());
                    bundleContentLoader.registerBundle(session, bundle, isUpdate);
                } catch (Throwable t) {
                    log.error(
                        "bundleChanged: Problem loading initial content of bundle "
                            + bundle.getSymbolicName() + " ("
                            + bundle.getBundleId() + ")", t);
                } finally {
                    this.ungetSession(session);
                }
                break;
            case BundleEvent.UPDATED:
                // we just add the symbolic name to the list of updated bundles
                // we will use this info when the new start event is triggered
                this.updatedBundles.add(bundle.getSymbolicName());
                break;
            case BundleEvent.UNINSTALLED:
                try {
                    session = this.getSession();
                    bundleContentLoader.unregisterBundle(session, bundle);
                } catch (Throwable t) {
                    log.error(
                        "bundleChanged: Problem unloading initial content of bundle "
                            + bundle.getSymbolicName() + " ("
                            + bundle.getBundleId() + ")", t);
                } finally {
                    this.ungetSession(session);
                }
                break;
        }
    }

    // ---------- Implementation helpers --------------------------------------

    /** Returns the MIME type from the MimeTypeService for the given name */
    @Override
    public String getMimeType(String name) {
        // local copy to not get NPE despite check for null due to concurrent
        // unbind
        MimeTypeService mts = mimeTypeService;
        return (mts != null) ? mts.getMimeType(name) : null;
    }

    @Override
    public void createRepositoryPath(final Session writerSession, final String repositoryPath)
    throws RepositoryException {
        if ( !writerSession.itemExists(repositoryPath) ) {
            Node node = writerSession.getRootNode();
            String path = repositoryPath.substring(1);
            int pos = path.lastIndexOf('/');
            if ( pos != -1 ) {
                final StringTokenizer st = new StringTokenizer(path.substring(0, pos), "/");
                while ( st.hasMoreTokens() ) {
                    final String token = st.nextToken();
                    if ( !node.hasNode(token) ) {
                        node.addNode(token, "sling:Folder");
                        node.save();
                    }
                    node = node.getNode(token);
                }
                path = path.substring(pos + 1);
            }
            if ( !node.hasNode(path) ) {
                node.addNode(path, "sling:Folder");
                node.save();
            }
        }
    }

    // ---------- SCR Integration ---------------------------------------------

    /** Activates this component, called by SCR before registering as a service */
    @Activate
    protected synchronized void activate(BundleContext bundleContext) {
        this.slingId = this.settingsService.getSlingId();
        this.bundleContentLoader = new BundleContentLoader(this, contentReaderWhiteboard);

        bundleContext.addBundleListener(this);

        Session session = null;
        try {
            session = this.getSession();
            this.createRepositoryPath(session, BUNDLE_CONTENT_NODE);
            log.debug(
                    "Activated - attempting to load content from all "
                    + "bundles which are neither INSTALLED nor UNINSTALLED");

            int ignored = 0;
            Bundle[] bundles = bundleContext.getBundles();
            for (Bundle bundle : bundles) {
                if ((bundle.getState() & (Bundle.INSTALLED | Bundle.UNINSTALLED)) == 0) {

                    // load content for bundles which are neither INSTALLED nor
                    // UNINSTALLED
                    try {
                        bundleContentLoader.registerBundle(session, bundle, false);
                    } catch (Throwable t) {
                        log.error(
                            "Problem loading initial content of bundle "
                                + bundle.getSymbolicName() + " ("
                                + bundle.getBundleId() + ")", t);
                    } finally {
                        if ( session.hasPendingChanges() ) {
                            session.refresh(false);
                        }
                    }
                } else {
                    ignored++;
                }

            }

            log.debug(
                    "Out of {} bundles, {} were not in a suitable state for initial content loading",
                    bundles.length, ignored
                    );

        } catch (Throwable t) {
            log.error("activate: Problem while loading initial content and"
                + " registering mappings for existing bundles", t);
        } finally {
            this.ungetSession(session);
        }
    }

    /** Deactivates this component, called by SCR to take out of service */
    @Deactivate
    protected synchronized void deactivate(BundleContext bundleContext) {
        bundleContext.removeBundleListener(this);

        if ( this.bundleContentLoader != null ) {
            this.bundleContentLoader.dispose();
            this.bundleContentLoader = null;
        }
    }

    // ---------- internal helper ----------------------------------------------

    /** Returns the JCR repository used by this service. */
    protected SlingRepository getRepository() {
        return repository;
    }

    /**
     * Returns an administrative session to the default workspace.
     */
    @Override
    public Session getSession()
    throws RepositoryException {
        return getRepository().loginAdministrative(null);
    }

    /**
     * Returns an administrative session for the named workspace.
     */
    @Override
    public Session getSession(final String workspace) throws RepositoryException {
        return getRepository().loginAdministrative(workspace);
    }

    /**
     * Return the administrative session and close it.
     */
    private void ungetSession(final Session session) {
        if ( session != null ) {
            try {
                session.logout();
            } catch (Throwable t) {
                log.error("Unable to log out of session: " + t.getMessage(), t);
            }
        }
    }

    /**
     * Return the bundle content info and make an exclusive lock.
     * @param session
     * @param bundle
     * @return The map of bundle content info or null.
     * @throws RepositoryException
     */
    @Override
    public Map<String, Object> getBundleContentInfo(final Session session, final Bundle bundle, boolean create)
    throws RepositoryException {
        final String nodeName = bundle.getSymbolicName();
        final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
        if ( !parentNode.hasNode(nodeName) ) {
            if ( !create ) {
                return null;
            }
            try {
                final Node bcNode = parentNode.addNode(nodeName, "nt:unstructured");
                bcNode.addMixin("mix:lockable");
                parentNode.save();
            } catch (RepositoryException re) {
                // for concurrency issues (running in a cluster) we ignore exceptions
                this.log.warn("Unable to create node " + nodeName, re);
                session.refresh(true);
            }
        }
        final Node bcNode = parentNode.getNode(nodeName);
        if ( bcNode.isLocked() ) {
            return null;
        }
        try {
            bcNode.lock(false, true);
        } catch (LockException le) {
            return null;
        }
        final Map<String, Object> info = new HashMap<>();
        if ( bcNode.hasProperty(PROPERTY_CONTENT_LOADED_AT)) {
            info.put(PROPERTY_CONTENT_LOADED_AT, bcNode.getProperty(PROPERTY_CONTENT_LOADED_AT).getDate());
        }
        if ( bcNode.hasProperty(PROPERTY_CONTENT_LOADED) ) {
            info.put(PROPERTY_CONTENT_LOADED,
                bcNode.getProperty(PROPERTY_CONTENT_LOADED).getBoolean());
        } else {
            info.put(PROPERTY_CONTENT_LOADED, false);
        }
        if ( bcNode.hasProperty(PROPERTY_UNINSTALL_PATHS) ) {
            final Value[] values = bcNode.getProperty(PROPERTY_UNINSTALL_PATHS).getValues();
            final String[] s = new String[values.length];
            for(int i=0; i<values.length; i++) {
                s[i] = values[i].getString();
            }
            info.put(PROPERTY_UNINSTALL_PATHS, s);
        }
        return info;
    }

    @Override
    public void unlockBundleContentInfo(final Session session,
                                        final Bundle  bundle,
                                        final boolean contentLoaded,
                                        final List<String> createdNodes)
    throws RepositoryException {
        final String nodeName = bundle.getSymbolicName();
        final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
        final Node bcNode = parentNode.getNode(nodeName);
        if ( contentLoaded ) {
            bcNode.setProperty(PROPERTY_CONTENT_LOADED, contentLoaded);
            bcNode.setProperty(PROPERTY_CONTENT_LOADED_AT, Calendar.getInstance());
            bcNode.setProperty(PROPERTY_CONTENT_LOADED_BY, this.slingId);
            bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_AT, (String)null);
            bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_BY, (String)null);
            if ( createdNodes != null && createdNodes.size() > 0 ) {
                bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, createdNodes.toArray(new String[createdNodes.size()]));
            }
            bcNode.save();
        }
        bcNode.unlock();
    }

    @Override
    public void contentIsUninstalled(final Session session,
                                     final Bundle  bundle) {
        final String nodeName = bundle.getSymbolicName();
        try {
            final Node parentNode = (Node)session.getItem(BUNDLE_CONTENT_NODE);
            if ( parentNode.hasNode(nodeName) ) {
                final Node bcNode = parentNode.getNode(nodeName);
                bcNode.setProperty(PROPERTY_CONTENT_LOADED, false);
                bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_AT, Calendar.getInstance());
                bcNode.setProperty(PROPERTY_CONTENT_UNLOADED_BY, this.slingId);
                bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, (String[])null);
                bcNode.save();
            }
        } catch (RepositoryException re) {
            this.log.error("Unable to update bundle content info.", re);
        }
    }
}
