/*
 * 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.base.internal.registry;

import java.util.ArrayList;
import java.util.List;

import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.NotNull;
import javax.servlet.ServletContextAttributeEvent;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeEvent;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestEvent;
import javax.servlet.ServletRequestListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingEvent;
import javax.servlet.http.HttpSessionEvent;
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;

import org.apache.felix.http.base.internal.handler.ListenerHandler;
import org.apache.felix.http.base.internal.logger.SystemLogger;
import org.apache.felix.http.base.internal.runtime.ListenerInfo;
import org.osgi.service.http.runtime.dto.FailedListenerDTO;
import org.osgi.service.http.runtime.dto.ListenerDTO;
import org.osgi.service.http.runtime.dto.ServletContextDTO;

/**
 * Per context event listener registry.
 */
public final class EventListenerRegistry implements
        HttpSessionListener,
        HttpSessionAttributeListener,
        HttpSessionIdListener,
        ServletContextAttributeListener,
        ServletRequestListener,
        ServletRequestAttributeListener
{
    /** Servlet context listeners. */
    private final ListenerMap<ServletContextListener> contextListeners = new ListenerMap<ServletContextListener>();

    /** Servlet context attribute listeners. */
    private final ListenerMap<ServletContextAttributeListener> contextAttributeListeners = new ListenerMap<ServletContextAttributeListener>();

    /** Session attribute listeners. */
    private final ListenerMap<HttpSessionAttributeListener> sessionAttributeListeners = new ListenerMap<HttpSessionAttributeListener>();

    /** Session listeners. */
    private final ListenerMap<HttpSessionListener> sessionListeners = new ListenerMap<HttpSessionListener>();

    /** Session id listeners. */
    private final ListenerMap<HttpSessionIdListener> sessionIdListeners = new ListenerMap<HttpSessionIdListener>();

    /** Request listeners. */
    private final ListenerMap<ServletRequestListener> requestListeners = new ListenerMap<ServletRequestListener>();

    /** Request attribute listeners. */
    private final ListenerMap<ServletRequestAttributeListener> requestAttributeListeners = new ListenerMap<ServletRequestAttributeListener>();

    public void cleanup()
    {
        this.contextListeners.cleanup();
        this.contextAttributeListeners.cleanup();
        this.sessionAttributeListeners.cleanup();
        this.sessionListeners.cleanup();
        this.sessionIdListeners.cleanup();
        this.requestListeners.cleanup();
        this.requestAttributeListeners.cleanup();
    }

    /**
     * Add  listeners
     *
     * @param listener handler
     */
    public void addListeners(@NotNull final ListenerHandler handler)
    {
        final int reason = handler.init();

        if ( handler.getListenerInfo().isListenerType(ServletContextListener.class.getName()))
        {
            this.contextListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(ServletContextAttributeListener.class.getName()))
        {
            this.contextAttributeListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(HttpSessionListener.class.getName()))
        {
            this.sessionListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(HttpSessionIdListener.class.getName()))
        {
            this.sessionIdListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(HttpSessionAttributeListener.class.getName()))
        {
            this.sessionAttributeListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(ServletRequestListener.class.getName()))
        {
            this.requestListeners.add(handler, reason);
        }
        if ( handler.getListenerInfo().isListenerType(ServletRequestAttributeListener.class.getName()))
        {
            this.requestAttributeListeners.add(handler, reason);
        }
    }

    /**
     * Remove listeners
     *
     * @param info
     */
    public void removeListeners(@NotNull final ListenerInfo info)
    {
        // each listener map returns the same handler, we just need it once to destroy
        ListenerHandler handler = null;
        if ( info.isListenerType(ServletContextListener.class.getName()))
        {
            handler = this.contextListeners.remove(info);
        }
        if ( info.isListenerType(ServletContextAttributeListener.class.getName()))
        {
            handler = this.contextAttributeListeners.remove(info);
        }
        if ( info.isListenerType(HttpSessionListener.class.getName()))
        {
            handler = this.sessionListeners.remove(info);
        }
        if ( info.isListenerType(HttpSessionIdListener.class.getName()))
        {
            handler = this.sessionIdListeners.remove(info);
        }
        if ( info.isListenerType(HttpSessionAttributeListener.class.getName()))
        {
            handler = this.sessionAttributeListeners.remove(info);
        }
        if ( info.isListenerType(ServletRequestListener.class.getName()))
        {
            handler = this.requestListeners.remove(info);
        }
        if ( info.isListenerType(ServletRequestAttributeListener.class.getName()))
        {
            handler = this.requestAttributeListeners.remove(info);
        }
        if ( handler != null )
        {
            handler.destroy();
        }
    }

    /**
     * Get the listener handler for the listener info
     * @param info The listener info
     * @return The handler or {@code null}.
     */
    public @Nullable ListenerHandler getServletContextListener(@NotNull final ListenerInfo info)
    {
        return this.contextListeners.getListenerHandler(info);
    }

    public void contextInitialized() {
        for (final ListenerHandler l : contextListeners.getActiveHandlers())
        {
            final ServletContextListener listener = (ServletContextListener)l.getListener();
            if ( listener != null )
            {
                contextInitialized(l.getListenerInfo(), listener, new ServletContextEvent(l.getContext()));
            }
        }
    }

    public void contextDestroyed() {
        for (final ListenerHandler l : contextListeners.getActiveHandlers())
        {
            final ServletContextListener listener = (ServletContextListener) l.getListener();
            if ( listener != null )
            {
                contextDestroyed(l.getListenerInfo(), listener, new ServletContextEvent(l.getContext()));
            }
        }
    }

    @Override
    public void attributeReplaced(final HttpSessionBindingEvent event)
    {
        for (final HttpSessionAttributeListener l : sessionAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeReplaced(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeRemoved(final HttpSessionBindingEvent event)
    {
        for (final HttpSessionAttributeListener l : sessionAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeRemoved(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeAdded(final HttpSessionBindingEvent event)
    {
        for (final HttpSessionAttributeListener l : sessionAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeAdded(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeReplaced(final ServletContextAttributeEvent event)
    {
        for (final ServletContextAttributeListener l : contextAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeReplaced(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeRemoved(final ServletContextAttributeEvent event)
    {
        for (final ServletContextAttributeListener l : contextAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeRemoved(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeAdded(final ServletContextAttributeEvent event)
    {
        for (final ServletContextAttributeListener l : contextAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeAdded(event);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void sessionCreated(final HttpSessionEvent se)
    {
        for (final HttpSessionListener l : sessionListeners.getActiveListeners())
        {
            try
            {
                l.sessionCreated(se);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void sessionDestroyed(final HttpSessionEvent se)
    {
        for (final HttpSessionListener l : sessionListeners.getActiveListeners())
        {
            try
            {
                l.sessionDestroyed(se);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void requestDestroyed(final ServletRequestEvent sre)
    {
        for (final ServletRequestListener l : requestListeners.getActiveListeners())
        {
            try
            {
                l.requestDestroyed(sre);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void requestInitialized(final ServletRequestEvent sre)
    {
        for (final ServletRequestListener l : requestListeners.getActiveListeners())
        {
            try
            {
                l.requestInitialized(sre);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeAdded(final ServletRequestAttributeEvent srae)
    {
        for (final ServletRequestAttributeListener l : requestAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeAdded(srae);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeRemoved(final ServletRequestAttributeEvent srae)
    {
        for (final ServletRequestAttributeListener l : requestAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeRemoved(srae);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    @Override
    public void attributeReplaced(final ServletRequestAttributeEvent srae)
    {
        for (final ServletRequestAttributeListener l : requestAttributeListeners.getActiveListeners())
        {
            try
            {
                l.attributeReplaced(srae);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    /**
     * @see javax.servlet.http.HttpSessionIdListener#sessionIdChanged(javax.servlet.http.HttpSessionEvent, java.lang.String)
     */
    @Override
    public void sessionIdChanged(@NotNull final HttpSessionEvent event, @NotNull final String oldSessionId) {
        for (final HttpSessionIdListener l : sessionIdListeners.getActiveListeners())
        {
            try
            {
                l.sessionIdChanged(event, oldSessionId);
            }
            catch (final Throwable t)
            {
                SystemLogger.error(null, "Exception while calling listener " + l, t);
            }
        }
    }

    public void getRuntimeInfo(final ServletContextDTO dto, final List<FailedListenerDTO> failedListenerDTOs)
    {
        final List<ListenerDTO> listenerDTOs = new ArrayList<ListenerDTO>();
        this.contextListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.contextAttributeListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.requestListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.requestAttributeListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.sessionListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.sessionAttributeListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);
        this.sessionIdListeners.getRuntimeInfo(listenerDTOs, failedListenerDTOs);

        if ( listenerDTOs.size() > 0 )
        {
            dto.listenerDTOs = listenerDTOs.toArray(new ListenerDTO[listenerDTOs.size()]);
        }
    }

    public static void contextInitialized(
            @NotNull final ListenerInfo info,
            @NotNull final ServletContextListener listener,
            @NotNull final ServletContextEvent event)
    {
        try
        {
            listener.contextInitialized(event);
        }
        catch (final Throwable t)
        {
            SystemLogger.error(info.getServiceReference(), "Exception while calling servlet context listener.", t);
        }
    }

    public static void contextDestroyed(
            @NotNull final ListenerInfo info,
            @NotNull final ServletContextListener listener,
            @NotNull final ServletContextEvent event)
    {
        try
        {
            listener.contextDestroyed(event);
        }
        catch (final Throwable t)
        {
            SystemLogger.error(info.getServiceReference(), "Exception while calling servlet context listener.", t);
        }
    }
}
