/*
 * 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.servlets.resolver.internal.resource;

import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_NAME;
import static org.osgi.framework.Constants.SERVICE_ID;
import static org.osgi.framework.Constants.SERVICE_PID;
import static org.osgi.service.component.ComponentConstants.COMPONENT_NAME;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import javax.servlet.Servlet;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;

import org.apache.sling.api.request.RequestUtil;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.servlets.ServletResolver;
import org.apache.sling.api.servlets.ServletResolverConstants;
import org.apache.sling.servlets.resolver.internal.ResolverConfig;
import org.apache.sling.spi.resource.provider.ResourceProvider;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
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.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>SlingServletResolver</code> resolves a
 * servlet for a request by implementing the {@link ServletResolver} interface.
 *
 * The resolver uses an own session to find the scripts.
 *
 */
@Component(configurationPid = ResolverConfig.PID,
           service = {})
public class ServletMounter {

    /** Logger */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final String REF_SERVLET = "Servlet";

    @Reference(target="(name=org.apache.sling)")
    private ServletContext servletContext;

    private final Map<ServiceReference<Servlet>, ServletReg> servletsByReference = new HashMap<>();

    private final List<PendingServlet> pendingServlets = new ArrayList<>();

    /** The bundle context. */
    private volatile BundleContext context;

    private volatile ServletResourceProviderFactory servletResourceProviderFactory;

    @Reference
    private ResourceResolverFactory resourceResolverFactory;

    /**
     * Activate this component.
     */
    @Activate
    protected void activate(final BundleContext context,
            final ResolverConfig config) {
        final Collection<PendingServlet> refs;
        synchronized (this.pendingServlets) {

            refs = new ArrayList<>(pendingServlets);
            pendingServlets.clear();

            servletResourceProviderFactory = new ServletResourceProviderFactory(config.servletresolver_servletRoot(),
                    resourceResolverFactory.getSearchPath());

            // register servlets immediately from now on
            this.context = context;
        }
        createAllServlets(refs);
    }

    /**
     * Deactivate this component.
     */
    @Deactivate
    protected void deactivate() {
        // stop registering of servlets immediately
        this.context = null;

        // Copy the list of servlets first, to minimize the need for
        // synchronization
        final Collection<ServiceReference<Servlet>> refs;
        synchronized (this.servletsByReference) {
            refs = new ArrayList<>(servletsByReference.keySet());
        }
        // destroy all servlets
        destroyAllServlets(refs);

        // sanity check: clear array (it should be empty now anyway)
        synchronized ( this.servletsByReference ) {
            this.servletsByReference.clear();
        }

        this.servletResourceProviderFactory = null;
    }

    // TODO
    // This can be simplified once we can use DS from R7 with constructor injection
    // as we can inject the bundle context through the constructor
    @Reference(
            name = REF_SERVLET,
            service = Servlet.class,
            cardinality = ReferenceCardinality.MULTIPLE,
            policy = ReferencePolicy.DYNAMIC,
            target="(|(" + ServletResolverConstants.SLING_SERVLET_PATHS + "=*)(" + ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES + "=*))")
    protected void bindServlet(final Servlet servlet, final ServiceReference<Servlet> reference) {
        boolean directCreate = true;
        if (context == null) {
            synchronized ( pendingServlets ) {
                if (context == null) {
                    pendingServlets.add(new PendingServlet(servlet, reference));
                    directCreate = false;
                }
            }
        }
        if ( directCreate ) {
            createServlet(servlet, reference);
        }
    }

    protected void unbindServlet(final ServiceReference<Servlet> reference) {
        synchronized ( pendingServlets ) {
            final Iterator<PendingServlet> iter = pendingServlets.iterator();
            while ( iter.hasNext() ) {
                final PendingServlet ps = iter.next();
                if ( ps.reference.compareTo(reference) == 0 ) {
                    iter.remove();
                    break;
                }
            }
        }
        destroyServlet(reference);
    }

    private void createAllServlets(final Collection<PendingServlet> pendingServlets) {
        for (final PendingServlet ps : pendingServlets) {
            createServlet(ps.servlet, ps.reference);
        }
    }


    private boolean createServlet(final Servlet servlet, final ServiceReference<Servlet> reference) {
        // check for a name, this is required
        final String name = getName(reference);

        // check for Sling properties in the service registration
        final ServletResourceProvider provider = servletResourceProviderFactory.create(reference, servlet);
        if (provider == null) {
            // this is expected if the servlet is not destined for Sling
            return false;
        }

        // initialize now
        try {
            servlet.init(new SlingServletConfig(servletContext, reference, name));
            logger.debug("bindServlet: Servlet {} initialized", name);
        } catch (final ServletException ce) {
            logger.error("bindServlet: Servlet " + ServletResourceProviderFactory.getServiceReferenceInfo(reference) + " failed to initialize", ce);
            return false;
        } catch (final Throwable t) {
            logger.error("bindServlet: Unexpected problem initializing servlet " + ServletResourceProviderFactory.getServiceReferenceInfo(reference), t);
            return false;
        }

        boolean registered = false;
        final Bundle bundle = reference.getBundle();
        if ( bundle != null ) {
            final BundleContext bundleContext = bundle.getBundleContext();
            if ( bundleContext != null ) {
                final List<ServiceRegistration<ResourceProvider<Object>>> regs = new ArrayList<>();
                try {
                    for(final String root : provider.getServletPaths()) {
                        @SuppressWarnings("unchecked")
                        final ServiceRegistration<ResourceProvider<Object>> reg = (ServiceRegistration<ResourceProvider<Object>>) bundleContext.registerService(
                            ResourceProvider.class.getName(),
                            provider,
                            createServiceProperties(reference, root));
                        regs.add(reg);
                    }
                    registered = true;
                } catch ( final IllegalStateException ise ) {
                    // bundle context not valid anymore - ignore and continue without this
                }
                if ( registered ) {
                    if ( logger.isDebugEnabled() ) {
                        logger.debug("Registered {}", provider);
                    }
                    synchronized (this.servletsByReference) {
                        servletsByReference.put(reference, new ServletReg(servlet, regs));
                    }
                }
            }
        }
        if ( !registered ) {
            logger.debug("bindServlet: servlet has been unregistered in the meantime. Ignoring {}", name);
        }

        return true;
    }

    private Dictionary<String, Object> createServiceProperties(final ServiceReference<Servlet> reference,
            final String root) {

        final Dictionary<String, Object> params = new Hashtable<>();
        params.put(ResourceProvider.PROPERTY_ROOT, root);
        params.put(Constants.SERVICE_DESCRIPTION,
            "ServletResourceProvider for Servlet at " + root);

        // inherit service ranking
        Object rank = reference.getProperty(Constants.SERVICE_RANKING);
        if (rank instanceof Integer) {
            params.put(Constants.SERVICE_RANKING, rank);
        }

        return params;
    }

    private void destroyAllServlets(final Collection<ServiceReference<Servlet>> refs) {
        for (ServiceReference<Servlet> serviceReference : refs) {
            destroyServlet(serviceReference);
        }
    }

    private void destroyServlet(final ServiceReference<Servlet> reference) {
        ServletReg registration;
        synchronized (this.servletsByReference) {
            registration = servletsByReference.remove(reference);
        }
        if (registration != null) {

            for(final ServiceRegistration<ResourceProvider<Object>> reg : registration.registrations) {
                try {
                    reg.unregister();
                } catch ( final IllegalStateException ise) {
                    // this might happen on shutdown
                }
            }
            final String name = RequestUtil.getServletName(registration.servlet);
            logger.debug("unbindServlet: Servlet {} removed", name);

            try {
                registration.servlet.destroy();
            } catch (Throwable t) {
                logger.error("unbindServlet: Unexpected problem destroying servlet " + name, t);
            }
        }
    }

    /** The list of property names checked by {@link #getName(ServiceReference)} */
    private static final String[] NAME_PROPERTIES = { SLING_SERVLET_NAME,
        COMPONENT_NAME, SERVICE_PID, SERVICE_ID };

    /**
     * Looks for a name value in the service reference properties. See the
     * class comment at the top for the list of properties checked by this
     * method.
     * @return The servlet name. This method never returns {@code null}
     */
    private static String getName(final ServiceReference<Servlet> reference) {
        String servletName = null;
        for (int i = 0; i < NAME_PROPERTIES.length
            && (servletName == null || servletName.length() == 0); i++) {
            Object prop = reference.getProperty(NAME_PROPERTIES[i]);
            if (prop != null) {
                servletName = String.valueOf(prop);
            }
        }
        return servletName;
    }

    private static final class ServletReg {
        public final Servlet servlet;
        public final List<ServiceRegistration<ResourceProvider<Object>>> registrations;

        public ServletReg(final Servlet s, final List<ServiceRegistration<ResourceProvider<Object>>> srs) {
            this.servlet = s;
            this.registrations = srs;
        }
    }

    private static final class PendingServlet {
        public final Servlet servlet;
        public final ServiceReference<Servlet> reference;

        public PendingServlet(final Servlet s, final ServiceReference<Servlet> ref) {
            this.servlet = s;
            this.reference = ref;
        }
    }
}
