/*
 * 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.serviceusermapping.ServiceUserMapped;
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.ConfigurationPolicy;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>BundleContentLoaderListener</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" }, configurationPolicy = ConfigurationPolicy.OPTIONAL)
@Designate(ocd = BundleContentLoaderConfiguration.class, factory = false)
public class BundleContentLoaderListener 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());

    /**
     * SLING-10015 - To require a service user before becoming active
     */
    @Reference
    private ServiceUserMapped serviceUserMapped;

    /**
     * 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 (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, BundleContentLoaderConfiguration configuration) {
        this.slingId = this.settingsService.getSlingId();
        this.bundleContentLoader = new BundleContentLoader(this, contentReaderWhiteboard, configuration);

        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);
        }
    }
}
