/*
 * 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 javax.jcr.lock.LockManager;

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;

    @Reference
    private SlingSettingsService slingSettings;

    /**
     * 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 (Exception 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 (Exception t) {
                    log.error(
                        "bundleChanged: Problem unloading initial content of bundle "
                            + bundle.getSymbolicName() + " ("
                            + bundle.getBundleId() + ")", t);
                } finally {
                    this.ungetSession(session);
                }
                break;
            default:
        }
    }

    // ---------- 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");
                        writerSession.save();
                    }
                    node = node.getNode(token);
                }
                path = path.substring(pos + 1);
            }
            if ( !node.hasNode(path) ) {
                node.addNode(path, "sling:Folder");
                writerSession.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, slingSettings.getRunModes());

        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
                    loadBundle(bundle, session);
                } else {
                    ignored++;
                }

            }

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

        } catch (Exception t) {
            log.error("activate: Problem while loading initial content and"
                + " registering mappings for existing bundles", t);
        } finally {
            this.ungetSession(session);
        }
    }
    
    private void loadBundle(Bundle bundle, Session session) throws RepositoryException {
        try {
            bundleContentLoader.registerBundle(session, bundle, false);
        } catch (Exception t) {
            log.error(
                "Problem loading initial content of bundle "
                    + bundle.getSymbolicName() + " ("
                    + bundle.getBundleId() + ")", t);
        } finally {
            if ( session.hasPendingChanges() ) {
                session.refresh(false);
            }
        }
    }

    /** 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().loginService(null, null);
    }

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

    /**
     * Return the administrative session and close it.
     */
    private void ungetSession(final Session session) {
        if ( session != null ) {
            try {
                session.logout();
            } catch (Exception 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");
                session.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 {
        	LockManager lockManager = session.getWorkspace().getLockManager();
        	lockManager.lock(bcNode.getPath(), 
        			false, // isDeep 
        			true, // isSessionScoped 
        			Long.MAX_VALUE, // timeoutHint 
        			null); // ownerInfo
        } 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.isEmpty() ) {
                bcNode.setProperty(PROPERTY_UNINSTALL_PATHS, createdNodes.toArray(new String[createdNodes.size()]));
            }
            session.save();
        }
        LockManager lockManager = session.getWorkspace().getLockManager();
		lockManager.unlock(bcNode.getPath());
    }

    @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);
                session.save();
            }
        } catch (RepositoryException re) {
            this.log.error("Unable to update bundle content info.", re);
        }
    }
}
