/*
 * 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 java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.servlet.Servlet;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.ServletResolverConstants;
import org.apache.sling.commons.osgi.PropertiesUtil;
import org.osgi.framework.Bundle;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_EXTENSIONS;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_METHODS;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_NAME;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_PATHS;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_PREFIX;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_RESOURCE_SUPER_TYPE;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_RESOURCE_TYPES;
import static org.apache.sling.api.servlets.ServletResolverConstants.SLING_SERVLET_SELECTORS;
import static org.osgi.service.component.ComponentConstants.COMPONENT_NAME;

public class ServletResourceProviderFactory {

    /**
     * The extension appended to servlets to register into the resource tree to
     * simplify handling in the resolution process (value is ".servlet").
     */
    public static final String SERVLET_PATH_EXTENSION = ".servlet";

    private static final String[] DEFAULT_SERVLET_METHODS = {
        HttpConstants.METHOD_GET, HttpConstants.METHOD_HEAD };

    private static final String ALL_METHODS = "*";

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

    /**
     * The root path to use for servlets registered with relative paths.
     */
    private final String servletRoot;

    /**
     * The index of the search path to be used as servlet root path
     */
    private final int servletRootIndex;

    /**
     * The search paths
     */
    private final List<String> searchPath;

    static String ensureServletNameExtension(final String servletPath) {
        if (servletPath.endsWith(SERVLET_PATH_EXTENSION)) {
            return servletPath;
        }

        return servletPath.concat(SERVLET_PATH_EXTENSION);
    }

    /**
     * Constructor
     * @param servletRoot The default value for the servlet root
     */
    public ServletResourceProviderFactory(String servletRoot, final List<String> searchPath) {
        this.searchPath = searchPath;
        // check if servletRoot specifies a number
        boolean isNumber = false;
        int index = -1;
        if (!servletRoot.startsWith("/") ) {
            try {
                index = Integer.valueOf(servletRoot);
                isNumber = true;
            } catch (NumberFormatException nfe) {
                // ignore
            }
        }
        if ( !isNumber ) {
            // ensure the root starts and ends with a slash
            if (!servletRoot.startsWith("/")) {
                servletRoot = "/".concat(servletRoot);
            }
            if (!servletRoot.endsWith("/")) {
                servletRoot = servletRoot.concat("/");
            }

            this.servletRoot = servletRoot;
            this.servletRootIndex = -1;
        } else {
            this.servletRoot = null;
            this.servletRootIndex = index;
        }
    }

    /**
     * Create a servlet resource provider for the servlet
     * @param ref The service reference for the servlet
     * @param servlet The servlet object itself
     * @return A servlet resource provider
     */
    public ServletResourceProvider create(final ServiceReference<Servlet> ref, final Servlet servlet) {

        final Set<String> pathSet = new HashSet<>();

        // check whether explicit paths are set
        addByPath(pathSet, ref);

        // now, we handle resource types, extensions and methods
        addByType(pathSet, ref);

        if (pathSet.isEmpty()) {
            if (log.isDebugEnabled()) {
                log.debug(
                    "create({}): ServiceReference has no registration settings, ignoring",
                    getServiceReferenceInfo(ref));
            }
            return null;
        }

        if (log.isDebugEnabled()) {
            log.debug("create({}): Registering servlet for paths {}",
                    getServiceReferenceInfo(ref), pathSet);
        }
        String resourceSuperType = PropertiesUtil.toString(ref.getProperty(SLING_SERVLET_RESOURCE_SUPER_TYPE), null);
        Set<String> resourceSuperTypeMarkers = new HashSet<>();
        if (StringUtils.isNotEmpty(resourceSuperType)) {
            for (String rt : PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_RESOURCE_TYPES))) {
                if (!rt.startsWith("/")) {
                    rt = getPrefix(ref).concat(ResourceUtil.resourceTypeToPath(rt));
                }
                resourceSuperTypeMarkers.add(rt);
                pathSet.add(rt);
            }
        }
        return new ServletResourceProvider(servlet, pathSet, resourceSuperTypeMarkers, resourceSuperType);
    }

    /**
     * Get the mount prefix.
     */
    private String getPrefix(final ServiceReference<Servlet> ref) {
        Object value = ref.getProperty(SLING_SERVLET_PREFIX);
        if ( value == null ) {
            if ( this.servletRoot != null ) {
                return this.servletRoot;
            }
            value = this.servletRootIndex;
        }
        int index = -1;
        if ( value instanceof Number ) {
            index = ((Number)value).intValue();
        } else {
            String s = value.toString();
            if ( !s.startsWith("/") ) {
                boolean isNumber = false;
                try {
                    index = Integer.valueOf(s);
                    isNumber = true;
                } catch (NumberFormatException nfe) {
                    // ignore
                }
                if ( !isNumber ) {
                    if (log.isDebugEnabled()) {
                        log.debug("getPrefix({}): Configuration property is ignored {}",
                                getServiceReferenceInfo(ref), value);
                    }
                    if ( this.servletRoot != null ) {
                        return this.servletRoot;
                    }
                    index = this.servletRootIndex;
                }
            } else {
                return s;
            }
        }
        if ( index == -1 || index >= this.searchPath.size() ) {
            index = this.searchPath.size() - 1;
        }
        return this.searchPath.get(index);
    }

    /**
     * Add a servlet by path.
     * @param pathSet
     * @param ref
     */
    private void addByPath(Set<String> pathSet, ServiceReference<Servlet> ref) {
        String[] paths = PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_PATHS));
        if (paths != null && paths.length > 0) {
            for (String path : paths) {
                if (!path.startsWith("/")) {
                    path = getPrefix(ref).concat(path);
                }

                // add the unmodified path
                pathSet.add(path);

                // ensure we have another entry which has the .servlet ext.
                pathSet.add(ensureServletNameExtension(path));
            }
        }
    }

    /**
     * Add a servlet by type
     * @param pathSet
     * @param ref
     */
    private void addByType(Set<String> pathSet, ServiceReference<Servlet> ref) {
        String[] types = PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_RESOURCE_TYPES));
        if (types == null || types.length == 0) {
            if (log.isDebugEnabled()) {
                log.debug("addByType({}): no resource types declared",
                        getServiceReferenceInfo(ref));
            }
            return;
        }

        // check for selectors
        String[] selectors = PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_SELECTORS));
        if (selectors == null) {
            selectors = new String[] { null };
        }

        // we have types and expect extensions and/or methods
        String[] extensions = PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_EXTENSIONS));

        // handle the methods property specially (SLING-430)
        String[] methods = PropertiesUtil.toStringArray(ref.getProperty(SLING_SERVLET_METHODS));
        if (methods == null || methods.length == 0) {

            // SLING-512 only, set default methods if no extensions are declared
            if (extensions == null || extensions.length == 0) {
                if (log.isDebugEnabled()) {
                    log.debug(
                        "addByType({}): No methods declared, assuming GET/HEAD",
                        getServiceReferenceInfo(ref));
                }
                methods = DEFAULT_SERVLET_METHODS;
            }

        } else if (methods.length == 1 && ALL_METHODS.equals(methods[0])) {
            if (log.isDebugEnabled()) {
                log.debug("addByType({}): Assuming all methods for '*'",
                        getServiceReferenceInfo(ref));
            }
            methods = null;
        }

        for (String type : types) {

            // ensure namespace prefixes are converted to slashes
            type = ResourceUtil.resourceTypeToPath(type);

            // make absolute if relative
            if (!type.startsWith("/")) {
                type = this.getPrefix(ref) + type;
            }

            // ensure trailing slash for full path building
            if (!type.endsWith("/")) {
                type += "/";
            }

            // add entries for each selector combined with each ext and method
            for (String selector : selectors) {

                String selPath = type;
                if (selector != null && selector.length() > 0) {
                    selPath += selector.replace('.', '/') + ".";
                }

                boolean pathAdded = false;
                if (extensions != null) {
                    if (methods != null) {
                        // both methods and extensions declared
                        for (String ext : extensions) {
                            for (String method : methods) {
                                pathSet.add(selPath + ext + "." + method
                                    + SERVLET_PATH_EXTENSION);
                                pathAdded = true;
                            }
                        }
                    } else {
                        // only extensions declared
                        for (String ext : extensions) {
                            pathSet.add(selPath + ext + SERVLET_PATH_EXTENSION);
                            pathAdded = true;
                        }
                    }
                } else if (methods != null) {
                    // only methods declared
                    for (String method : methods) {
                        pathSet.add(selPath + method + SERVLET_PATH_EXTENSION);
                        pathAdded = true;
                    }
                }

                // if neither methods nore extensions were added
                if (!pathAdded) {
                    pathSet.add(selPath.substring(0, selPath.length() - 1)
                        + SERVLET_PATH_EXTENSION);
                }
            }
        }
    }

    public static String getServiceReferenceInfo(final ServiceReference<Servlet> reference) {
        final StringBuilder sb = new StringBuilder("service ");
        sb.append(String.valueOf(reference.getProperty(Constants.SERVICE_ID)));
        final Object servletName = reference.getProperty(SLING_SERVLET_NAME);
        final Object pid = reference.getProperty(Constants.SERVICE_PID);
        Object componentName = reference.getProperty(COMPONENT_NAME);
        if ( pid != null && pid.equals(componentName) ) {
            componentName = null;
        }
        if ( servletName != null || pid != null || componentName != null ) {
            sb.append(" (");
            boolean needsComma = false;
            if ( servletName != null ) {
                sb.append("name=");
                sb.append(servletName);
                needsComma = true;
            }
            if ( pid != null ) {
                if ( needsComma ) {
                    sb.append(", ");
                }
                sb.append("pid=");
                sb.append(pid);
                needsComma = true;
            }
            if ( componentName != null ) {
                if ( needsComma ) {
                    sb.append(", ");
                }
                sb.append("component=");
                sb.append(componentName);
                needsComma = true;
            }
            sb.append(")");
        }
        sb.append(" from ");
        final Bundle bundle = reference.getBundle();
        if ( bundle == null ) {
            sb.append("uninstalled bundle");
        } else {
            sb.append("bundle ");
            if ( bundle.getSymbolicName() == null ) {
                sb.append(String.valueOf(bundle.getBundleId()));
            } else {
                sb.append(bundle.getSymbolicName());
                sb.append(":");
                sb.append(bundle.getVersion());
                sb.append(" (");
                sb.append(String.valueOf(bundle.getBundleId()));
                sb.append(") ");
            }
        }
        final String[] ocs = (String[]) reference.getProperty("objectClass");
        if ( ocs != null ) {
            sb.append("[");
            for(int i = 0; i < ocs.length; i++) {
                sb.append(ocs[i]);
                if (i < ocs.length - 1) {
                    sb.append(", ");
                }
            }
            sb.append("]");
        }
        return sb.toString();
    }
}
