/**
 * Licensed 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
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * 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.winegrower.servlet.service;

import org.apache.winegrower.Ripener;
import org.apache.winegrower.api.LifecycleCallbacks;
import org.apache.winegrower.scanner.manifest.ManifestContributor;
import org.osgi.framework.BundleContext;
import org.osgi.framework.ServiceReference;
import org.osgi.service.http.HttpService;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;

import javax.servlet.Filter;
import javax.servlet.Servlet;
import javax.servlet.ServletContainerInitializer;
import javax.servlet.ServletContext;
import javax.servlet.ServletContextAttributeListener;
import javax.servlet.ServletContextEvent;
import javax.servlet.ServletContextListener;
import javax.servlet.ServletRequestAttributeListener;
import javax.servlet.ServletRequestListener;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebListener;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpSessionActivationListener;
import javax.servlet.http.HttpSessionAttributeListener;
import javax.servlet.http.HttpSessionBindingListener;
import javax.servlet.http.HttpSessionIdListener;
import javax.servlet.http.HttpSessionListener;
import java.io.File;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.EventListener;
import java.util.Hashtable;
import java.util.Set;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collector;
import java.util.stream.Stream;

import static java.util.Arrays.asList;
import static java.util.Optional.of;
import static java.util.Optional.ofNullable;
import static java.util.stream.Collectors.toList;

public class ServletHttpServiceDeployer implements ServletContainerInitializer {

    @Override
    public void onStartup(final Set<Class<?>> c, final ServletContext servletContext) {
        if (getClass() == ServletHttpServiceDeployer.class &&
                is(servletContext, "winegrower.servlet.ripener.skip", false)) {
            return;
        }
        final Ripener.Configuration configuration = createConfiguration(servletContext);
        final Ripener.Impl ripener = new Ripener.Impl(configuration);
        onRipenerCreated(ripener);
        if (is(servletContext, "winegrower.servlet.services.http.register", true)) {
            final ServletHttpService service = new ServletHttpService(servletContext);
            ripener.registerBuiltInService(HttpService.class, service, new Hashtable<>());
            final BundleContext rootBundle = ripener.getRegistry().getBundles().get(0L).getBundle().getBundleContext();
            Stream.of(Servlet.class, HttpServlet.class).forEach(base -> registerServletTracker(service, rootBundle, base));
            registerFilterTracker(service, rootBundle);
            Stream.of(
                    ServletContextListener.class, ServletContextAttributeListener.class,
                    HttpSessionListener.class, HttpSessionAttributeListener.class,
                    HttpSessionActivationListener.class, HttpSessionBindingListener.class,
                    HttpSessionIdListener.class,
                    ServletRequestListener.class, ServletRequestAttributeListener.class)
                    .forEach(base -> registerListenerTracker(service, rootBundle, base));
        }
        servletContext.setAttribute(Ripener.class.getName(), ripener.start());
        onRipenerStarted(ripener);
        servletContext.addListener(new ServletContextListener() {

            @Override
            public void contextDestroyed(final ServletContextEvent sce) {
                ofNullable(sce.getServletContext().getAttribute(Ripener.class.getName()))
                        .map(Ripener.class::cast)
                        .map(it -> {
                            onRipenerWillStop(it);
                            return it;
                        })
                        .ifPresent(Ripener::stop);
            }
        });
    }

    // enables subclasses to register built in services
    protected void onRipenerCreated(final Ripener ripener) {
        // no-op
    }

    protected void onRipenerWillStop(final Ripener ripener) {
        // no-op
    }

    // enables subclasses to wait for some start (OSGi-CDI typically)
    protected void onRipenerStarted(final Ripener ripener) {
        // no-op
    }

    private Boolean is(final ServletContext servletContext, final String name, final boolean def) {
        return ofNullable(servletContext.getInitParameter(name)).map(String::valueOf).map(Boolean::parseBoolean).orElse(def);
    }

    private <T extends EventListener> void registerListenerTracker(final ServletHttpService service, final BundleContext bundleContext,
                                                                   final Class<T> type) {
        new StartupOnlyTracker<>(bundleContext, type, (reference, listener) -> {
            final Hashtable<String, Object> props = Stream.of(reference.getPropertyKeys()).map(String::valueOf)
                    .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> {
                        a.putAll(b);
                        return a;
                    }));
            ofNullable(listener.getClass().getAnnotation(WebListener.class))
                    .ifPresent(annotConfig -> of(annotConfig.value())
                            .filter(it -> !it.isEmpty())
                            .ifPresent(value -> props.put("description", value)));
            service.registerListener(listener, props);
        }).open();
    }

    private void registerFilterTracker(final ServletHttpService service, final BundleContext bundleContext) {
        new StartupOnlyTracker<>(bundleContext, Filter.class, (reference, filter) -> {
            final Hashtable<String, Object> props = Stream.of(reference.getPropertyKeys()).map(String::valueOf)
                    .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> {
                        a.putAll(b);
                        return a;
                    }));
            ofNullable(filter.getClass().getAnnotation(WebFilter.class)).ifPresent(annotConfig -> {
                of(annotConfig.asyncSupported()).filter(it -> it).ifPresent(value -> props.put("async-supported", value));
                of(annotConfig.displayName()).filter(it -> !it.isEmpty()).ifPresent(value -> props.put("display-name", value));
            });
            findMapping(reference, filter, WebFilter.class, WebFilter::urlPatterns)
                    .forEach(mapping -> service.registerFilter(mapping, filter, props));
        }).open();
    }

    private <T extends Servlet> void registerServletTracker(final ServletHttpService service, final BundleContext bundleContext,
                                                            final Class<T> base) {
        new StartupOnlyTracker<>(bundleContext, base, (reference, servlet) -> {
            final Hashtable<String, Object> props = toProps(reference);
            ofNullable(servlet.getClass().getAnnotation(WebServlet.class)).ifPresent(annotConfig -> {
                props.put("servlet-name",
                        of(annotConfig.name()).filter(it -> !it.isEmpty()).orElse(servlet.getClass().getName()));
                of(annotConfig.loadOnStartup()).filter(it -> it >= 0).ifPresent(value -> props.put("load-on-startup", value));
                of(annotConfig.asyncSupported()).filter(it -> it).ifPresent(value -> props.put("async-supported", value));
                of(annotConfig.displayName()).filter(it -> !it.isEmpty()).ifPresent(value -> props.put("display-name", value));
            });
            findMapping(reference, servlet, WebServlet.class, WebServlet::urlPatterns)
                    .forEach(mapping -> service.registerServlet(mapping, servlet, props, null));
        }).open();
    }

    private <T, A extends Annotation> Stream<String> findMapping(final ServiceReference<T> reference, final T servlet,
                                                                 final Class<A> holder, final Function<A, String[]> mappingExtractor) {
        return ofNullable(servlet.getClass().getAnnotation(holder)).map(mappingExtractor).filter(it -> it.length > 0)
                .map(Stream::of).orElseGet(() -> ofNullable(reference.getProperty("alias")).map(String::valueOf).map(Stream::of)
                        .orElseGet(Stream::empty));
    }

    private Hashtable<String, Object> toProps(final ServiceReference<?> reference) {
        return Stream.of(reference.getPropertyKeys()).map(String::valueOf)
                .collect(Collector.of(Hashtable::new, (out, key) -> out.put(key, reference.getProperty(key)), (a, b) -> {
                    a.putAll(b);
                    return a;
                }));
    }

    private Ripener.Configuration createConfiguration(final ServletContext servletContext) {
        final Ripener.Configuration configuration = new Ripener.Configuration();
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.useLifecycleCallbacks"))
                .map(String::valueOf)
                .map(Boolean::parseBoolean)
                .ifPresent(configuration::setUseLifecycleCallbacks);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.workdir")).map(String::valueOf)
                .map(File::new).ifPresent(configuration::setWorkDir);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.prioritizedBundles"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(",")))
                .ifPresent(configuration::setPrioritizedBundles);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.ignoredBundles"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(",")))
                .ifPresent(configuration::setIgnoredBundles);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.scanningIncludes"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(",")))
                .ifPresent(configuration::setScanningIncludes);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.scanningExcludes"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(",")))
                .ifPresent(configuration::setScanningExcludes);
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.manifestContributors"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))).ifPresent(contributors -> {
            configuration.setManifestContributors(contributors.stream().map(clazz -> {
                try {
                    return Thread.currentThread().getContextClassLoader().loadClass(clazz).getConstructor().newInstance();
                } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException
                        | ClassNotFoundException e) {
                    throw new IllegalArgumentException(e);
                } catch (final InvocationTargetException e) {
                    throw new IllegalArgumentException(e.getTargetException());
                }
            }).map(ManifestContributor.class::cast).collect(toList()));
        });
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.lifecycleCallbacks"))
                .map(String::valueOf).filter(it -> !it.isEmpty()).map(it -> asList(it.split(","))).ifPresent(lifecycleCallbacks -> {
            configuration.setLifecycleCallbacks(lifecycleCallbacks.stream().map(clazz -> {
                try {
                    return Thread.currentThread().getContextClassLoader().loadClass(clazz).getConstructor().newInstance();
                } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException
                        | ClassNotFoundException e) {
                    throw new IllegalArgumentException(e);
                } catch (final InvocationTargetException e) {
                    throw new IllegalArgumentException(e.getTargetException());
                }
            }).map(LifecycleCallbacks.class::cast).collect(toList()));
        });
        ofNullable(servletContext.getInitParameter("winegrower.servlet.ripener.configuration.jarFilter")).map(String::valueOf)
                .filter(it -> !it.isEmpty()).ifPresent(filter -> {
            try {
                configuration.setJarFilter((Predicate<String>) Thread.currentThread().getContextClassLoader()
                        .loadClass(filter).getConstructor().newInstance());
            } catch (final InstantiationException | NoSuchMethodException | IllegalAccessException
                    | ClassNotFoundException e) {
                throw new IllegalArgumentException(e);
            } catch (final InvocationTargetException e) {
                throw new IllegalArgumentException(e.getTargetException());
            }
        });
        return configuration;
    }

    private static class StartupOnlyTracker<A> extends ServiceTracker<A, A> {

        private StartupOnlyTracker(final BundleContext context,
                                   final Class<A> type,
                                   final BiConsumer<ServiceReference<A>, A> onService) {
            super(context, type, new ServiceTrackerCustomizer<A, A>() {

                @Override
                public A addingService(final ServiceReference<A> reference) {
                    final A service = context.getService(reference);
                    onService.accept(reference, service);
                    return service;
                }

                @Override
                public void modifiedService(final ServiceReference<A> reference, final A service) {
                    // no-op
                }

                @Override
                public void removedService(final ServiceReference<A> reference, final A service) {
                    // no-op
                }
            });
        }
    }
}
