/*
 * 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.felix.http.whiteboard.internal.manager;

import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Dictionary;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionListener;

import org.apache.felix.http.base.internal.logger.SystemLogger;
import org.apache.felix.http.whiteboard.HttpWhiteboardConstants;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.service.http.HttpContext;
import org.osgi.service.http.context.ServletContextHelper;

@SuppressWarnings("deprecation")
public final class ExtenderManager
{
    private static final String MARKER = "org.apache.felix.http.whiteboard";

    public enum Type {
        CONTEXT,
        FILTER,
        SERVLET,
        LISTENERS
    }

    private final Map<String, ServiceRegistration<?>> registrations = new ConcurrentHashMap<>();

    /**
     * Remove a service registration (if existing)
     * @param type The type
     * @param ref The service reference
     */
    private void removeServiceRegistration(final Type type, final ServiceReference<?> ref)
    {
        final ServiceRegistration<?> reg = this.registrations.remove(type.name() + String.valueOf(ref.getProperty(Constants.SERVICE_ID)));
        if ( reg != null )
        {
            try
            {
                reg.unregister();
            }
            catch ( final IllegalStateException ignore)
            {
                // we ignore this
            }
        }
    }

    /**
     * Add a service registration
     * @param type The type of the registration
     * @param ref The service reference
     * @param reg The service registration
     */
    private void putServiceRegistration(final Type type, final ServiceReference<?> ref, final ServiceRegistration<?> reg)
    {
        this.registrations.put(type.name() + String.valueOf(ref.getProperty(Constants.SERVICE_ID)), reg);
    }

    /**
     * Get a string property
     * @param ref The service reference
     * @param key The name of the property
     * @return The value of the property if the type is String, {@code null} otherwise
     */
    private String getStringProperty(final ServiceReference<?> ref, final String key)
    {
        Object value = ref.getProperty(key);
        return (value instanceof String) ? (String)value : null;
    }

    /**
     * Get the boolean property.
     * @param ref The service reference
     * @param key The name of the property
     * @return The value of the boolean property. Returns {@code false} as default
     */
    private boolean getBooleanProperty(final ServiceReference<?> ref, final String key)
    {
        Object value = ref.getProperty(key);
        if (value instanceof String)
        {
            return Boolean.valueOf((String) value);
        }
        else if (value instanceof Boolean)
        {
            return ((Boolean) value).booleanValue();
        }
        return false;
    }

   /**
     * Add the init parameters
     * @param ref The service reference
     * @param prefix The prefix to use
     * @param props The properties
     */
    private void addInitParams(final ServiceReference<?> ref, final String prefix, final Dictionary<String, Object> props)
    {
        for (final String key : ref.getPropertyKeys()) {
            if (key.startsWith(HttpWhiteboardConstants.INIT_PREFIX)) {
                final String paramKey = key.substring(HttpWhiteboardConstants.INIT_PREFIX.length());
                final Object paramValue = ref.getProperty(paramKey);

                if (paramValue != null) {
                    props.put(prefix + paramKey, paramValue);
                }
            }
        }
    }

    /**
     * Add the service ranking (if available)
     * @param ref The service reference
     * @param props The new properties
     */
    private void addServiceRanking(final ServiceReference<?> ref, final Dictionary<String, Object> props)
    {
        // we don't care about the type and assume it's correct
        final Object val = ref.getProperty(Constants.SERVICE_RANKING);
        if ( val != null )
        {
            props.put(Constants.SERVICE_RANKING, val);
        }
    }

    /**
     * Add the context select property
     * @param ref The service reference
     * @param props The properties
     */
    private void addHttpContextSelect(final ServiceReference<?> ref, final Dictionary<String, Object> props)
    {
        final String contextId = getStringProperty(ref, HttpWhiteboardConstants.CONTEXT_ID);
        // if context id is missing, the default context is used
        if ( contextId != null )
        {
            final StringBuilder select = new StringBuilder();
            select.append("(!(");
            select.append(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
            select.append('=');
            select.append(getHttpContextName(ref, contextId, false));
            select.append(")(");
            select.append(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME);
            select.append('=');
            select.append(getHttpContextName(ref, contextId, true));
            select.append("))");
            props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT, select.toString());
        }
        else
        {
            props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT,
                    "(" + org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME
                    + "=org.osgi.service.http)");
        }
    }

    /**
     * Return the http context name
     * @param ref The service reference
     * @return The name or {@code null}
     */
    private String getHttpContextName(final ServiceReference<?> ref,
            final String contextId,
            final boolean shared)
    {
        final StringBuilder name = new StringBuilder();
        name.append(MARKER);
        name.append('.');
        if ( shared )
        {
            name.append("shared");
        }
        else
        {
            name.append(ref.getBundle().getBundleId());
        }
        name.append('.');
        name.append(contextId);

        return name.toString();
    }

    /**
     * Add a HttpContext
     * @param service The HttpContext
     * @param ref The service reference
     */
    public void addHttpContext(final HttpContext service, final ServiceReference<HttpContext> ref)
    {
        final String contextId = getStringProperty(ref, HttpWhiteboardConstants.CONTEXT_ID);
        if (contextId != null && !contextId.isEmpty())
        {
            final boolean shared = getBooleanProperty(ref, HttpWhiteboardConstants.CONTEXT_SHARED);
            final String contextName = getHttpContextName(ref, contextId, shared);
            final Dictionary<String, Object> props = new Hashtable<>();
            props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME, contextName);
            props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_PATH, "/");
            props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_SERVICE_CONTEXT_PROPERTY, "true");
            props.put(MARKER + ".id", contextId);
            props.put(MARKER, "true");
            this.addServiceRanking(ref, props);
            final ServiceRegistration<ServletContextHelper> reg = ref.getBundle().getBundleContext().registerService(
                    ServletContextHelper.class,
                    new ServletContextHelper() {

                        @Override
                        public boolean handleSecurity(final HttpServletRequest request, final HttpServletResponse response)
                                throws IOException {
                            return service.handleSecurity(request, response);
                        }

                        @Override
                        public URL getResource(final String name) {
                            return service.getResource(name);
                        }

                        @Override
                        public String getMimeType(final String name) {
                            return service.getMimeType(name);
                        }

                    },
                    props);
            this.putServiceRegistration(Type.CONTEXT, ref, reg);
        }
        else
        {
            SystemLogger.debug("Ignoring HttpContext Service " + ref + ", " + HttpWhiteboardConstants.CONTEXT_ID
                + " is missing or empty");
        }
    }

    /**
     * Remove a HttpContext
     * @param ref The service reference
     */
    public void removeHttpContext(final ServiceReference<HttpContext> ref)
    {
        this.removeServiceRegistration(Type.CONTEXT, ref);
    }

    /**
     * Add a filter.
     * @param service The filter
     * @param ref The filter reference
     */
    public void addFilter(final Filter service, final ServiceReference<Filter> ref)
    {
        final String pattern = getStringProperty(ref, HttpWhiteboardConstants.PATTERN);

        if (pattern == null || pattern.isEmpty()) {
            SystemLogger.debug("Ignoring Filter Service " + ref + ", " + HttpWhiteboardConstants.PATTERN
                + " is missing or empty");
            return;
        }

        final Dictionary<String, Object> props = new Hashtable<>();
        props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_FILTER_REGEX, pattern);
        props.put(MARKER, "true");
        this.addHttpContextSelect(ref, props);
        this.addInitParams(ref, org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX, props);
        this.addServiceRanking(ref, props);

        final ServiceRegistration<Filter> reg = ref.getBundle().getBundleContext().registerService(
                Filter.class,
                service,
                props);
        this.putServiceRegistration(Type.FILTER, ref, reg);
    }

    /**
     * Add a servlet.
     * @param service The servlet
     * @param ref The service reference
     */
    public void addServlet(final Servlet service, final ServiceReference<Servlet> ref)
    {
        final String alias = getStringProperty(ref, HttpWhiteboardConstants.ALIAS);
        if (alias == null || alias.isEmpty() || !alias.startsWith("/"))
        {
            SystemLogger.debug("Ignoring Servlet Service " + ref + ", " + HttpWhiteboardConstants.ALIAS
                + " is missing, empty or invalid");
            return;
        }

        final Dictionary<String, Object> props = new Hashtable<>();
        props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN, alias);
        props.put(MARKER, "true");
        this.addHttpContextSelect(ref, props);
        this.addInitParams(ref, org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_INIT_PARAM_PREFIX, props);
        this.addServiceRanking(ref, props);

        final ServiceRegistration<Servlet> reg = ref.getBundle().getBundleContext().registerService(
                Servlet.class,
                service,
                props);
        this.putServiceRegistration(Type.SERVLET, ref, reg);
    }

    /**
     * Add listeners
     * @param service The service
     * @param ref The service reference
     */
    public void addListeners(final EventListener service, ServiceReference<EventListener> ref)
    {
        final Dictionary<String, Object> props = new Hashtable<>();
        final List<String> names = new ArrayList<>();
        if ( service instanceof HttpSessionAttributeListener)
        {
            names.add(HttpSessionAttributeListener.class.getName());
        }
        if ( service instanceof HttpSessionListener)
        {
            names.add(HttpSessionListener.class.getName());
        }
        if ( service instanceof ServletContextAttributeListener)
        {
            names.add(ServletContextAttributeListener.class.getName());
        }
        if ( service instanceof ServletRequestAttributeListener)
        {
            names.add(ServletRequestAttributeListener.class.getName());
        }
        if ( service instanceof ServletRequestListener)
        {
            names.add(ServletRequestListener.class.getName());
        }

        props.put(MARKER, "true");
        props.put(org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_LISTENER, "true");
        this.addHttpContextSelect(ref, props);
        this.addServiceRanking(ref, props);

        final ServiceRegistration<?> reg = ref.getBundle().getBundleContext().registerService(
                names.toArray(new String[names.size()]),
                service,
                props);
        this.putServiceRegistration(Type.LISTENERS, ref, reg);
    }


    /**
     * Remove a filter
     * @param ref The filter reference
     */
    public void removeFilter(final ServiceReference<Filter> ref)
    {
        this.removeServiceRegistration(Type.FILTER, ref);
    }

    /**
     * Remove a servlet
     * @param ref The service reference
     */
    public void removeServlet(final ServiceReference<Servlet> ref)
    {
        this.removeServiceRegistration(Type.SERVLET, ref);
    }

    /**
     * Remove a listener
     * @param ref The service reference
     */
    public void removeListeners(final ServiceReference<EventListener> ref)
    {
        this.removeServiceRegistration(Type.LISTENERS, ref);
    }
}
