/*
 * 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.aries.jax.rs.whiteboard.activator;

import javax.servlet.Servlet;
import javax.ws.rs.core.Application;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.ext.RuntimeDelegate;

import org.apache.aries.jax.rs.whiteboard.internal.CXFJaxRsServiceRegistrator;
import org.apache.aries.jax.rs.whiteboard.internal.CXFJaxRsServiceRegistrator.ServiceInformation;
import org.apache.aries.osgi.functional.OSGi;
import org.apache.aries.osgi.functional.OSGiResult;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.bus.CXFBusFactory;
import org.apache.cxf.jaxrs.lifecycle.ResourceProvider;
import org.apache.cxf.message.Message;
import org.apache.cxf.transport.servlet.CXFNonSpringServlet;
import org.osgi.framework.BundleActivator;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceObjects;
import org.osgi.framework.ServiceReference;
import org.osgi.framework.ServiceRegistration;
import org.osgi.framework.wiring.BundleWiring;

import java.util.Dictionary;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;

import static org.apache.aries.osgi.functional.OSGi.bundleContext;
import static org.apache.aries.osgi.functional.OSGi.just;
import static org.apache.aries.osgi.functional.OSGi.onClose;
import static org.apache.aries.osgi.functional.OSGi.register;
import static org.apache.aries.osgi.functional.OSGi.serviceReferences;
import static org.apache.aries.osgi.functional.OSGi.services;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_NAME;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_CONTEXT_SELECT;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME;
import static org.osgi.service.http.whiteboard.HttpWhiteboardConstants.HTTP_WHITEBOARD_SERVLET_PATTERN;

public class CXFJaxRsBundleActivator implements BundleActivator {

    private BundleContext _bundleContext;
    private OSGiResult<?> _applicationsResult;
    private OSGiResult<?> _singletonsResult;
    private OSGiResult<?> _extensionsResult;
    private OSGiResult<?> _applicationSingletonsResult;

    private static <T> OSGi<T> service(ServiceReference<T> serviceReference) {
        return
            bundleContext().flatMap(bundleContext ->
            onClose(() -> bundleContext.ungetService(serviceReference)).then(
            just(bundleContext.getService(serviceReference))
        ));
    }

    private static <T> OSGi<ServiceObjects<T>> serviceObjects(
        ServiceReference<T> serviceReference) {

        return
            bundleContext().flatMap(bundleContext ->
            just(bundleContext.getServiceObjects(serviceReference))
        );
    }

    private static OSGi<CXFJaxRsServiceRegistrator> cxfRegistrator(
        Bus bus, Application application, Map<String, Object> props) {

        CXFJaxRsServiceRegistrator registrator =
            new CXFJaxRsServiceRegistrator(bus, application, props);

        return
            onClose(registrator::close).then(
            register(CXFJaxRsServiceRegistrator.class, registrator, props).then(
            just(registrator)
        ));
    }

    @Override
    public void start(BundleContext bundleContext) throws Exception {
        _bundleContext = bundleContext;
        initRuntimeDelegate(bundleContext);

        // TODO make the context path of the JAX-RS Whiteboard configurable.
        Bus bus = BusFactory.newInstance(
            CXFBusFactory.class.getName()).createBus();
        registerCXFServletService(bus);

        OSGi<?> applications =
            serviceReferences(Application.class, getApplicationFilter()).
                flatMap(ref ->
            just(
                CXFJaxRsServiceRegistrator.getProperties(
                    ref, "osgi.jaxrs.application.base")).
                flatMap(properties ->
            service(ref).flatMap(application ->
            cxfRegistrator(bus, application, properties)
        )));

        _applicationsResult = applications.run(bundleContext);

        Application defaultApplication = new Application() {};

        CXFJaxRsServiceRegistrator defaultServiceRegistrator =
            new CXFJaxRsServiceRegistrator(
                bus, defaultApplication, new HashMap<>());

        OSGi<?> singletons =
            serviceReferences(getSingletonsFilter()).
                flatMap(serviceReference ->
            waitForExtensionDependencies(serviceReference,
                just(
                    CXFJaxRsServiceRegistrator.getProperties(
                        serviceReference, "osgi.jaxrs.resource.base")).
                    flatMap(properties ->
                service(serviceReference).flatMap(service ->
                safeRegisterEndpoint(
                    serviceReference, defaultServiceRegistrator)
            )))
        );

        _singletonsResult = singletons.run(bundleContext);

        OSGi<?> extensions =
            serviceReferences(getExtensionFilter()).flatMap(ref ->
            waitForExtensionDependencies(ref,
                safeRegisterExtension(ref, defaultServiceRegistrator)
            )
        );

        _extensionsResult = extensions.run(bundleContext);

        OSGi<?> applicationSingletons =
            serviceReferences("(osgi.jaxrs.application.select=*)").
                flatMap(ref ->
            just(ref.getProperty("osgi.jaxrs.application.select").toString()).
                flatMap(applicationFilter ->
            services(CXFJaxRsServiceRegistrator.class, applicationFilter).
                flatMap(registrator ->
            testProvider(ref).flatMap(isProvider -> {
                if (isProvider) {
                    return safeRegisterExtension(ref, registrator);
                }
                else {
                    return safeRegisterEndpoint(ref, registrator);
                }
            })
        )));

        _applicationSingletonsResult = applicationSingletons.run(bundleContext);
    }

    private OSGi<Boolean> testProvider(ServiceReference<?> serviceReference) {
        return bundleContext().flatMap(bundleContext -> {
            Object service = bundleContext.getService(serviceReference);
            Class<?> serviceClass = service.getClass();
            if (serviceClass.isAnnotationPresent(Provider.class)) {
                return just(Boolean.TRUE);
            }
            else {
                return just(Boolean.FALSE);
            }
        });
    }

    private OSGi<?> safeRegisterExtension(
        ServiceReference<Object> ref,
        CXFJaxRsServiceRegistrator registrator) {

        return
            service(ref).flatMap(extension ->
            onClose(() -> registrator.removeProvider(extension)).
                foreach(ign ->
            registrator.addProvider(extension)
        ));
    }

    /**
     * Initialize instance so it is never looked up again
     * @param bundleContext
     */
    private void initRuntimeDelegate(BundleContext bundleContext) {
        Thread thread = Thread.currentThread();
        ClassLoader oldClassLoader = thread.getContextClassLoader();
        BundleWiring bundleWiring = bundleContext.getBundle().adapt(
            BundleWiring.class);
        thread.setContextClassLoader(bundleWiring.getClassLoader());
        try {
            RuntimeDelegate.getInstance();
        }
        finally {
            thread.setContextClassLoader(oldClassLoader);
        }
    }

    private String[] canonicalize(Object propertyValue) {
        if (propertyValue == null) {
            return new String[0];
        }
        if (propertyValue instanceof String[]) {
            return (String[]) propertyValue;
        }
        return new String[]{propertyValue.toString()};
    }

    private String buildExtensionFilter(String filter) {
        return "(&(osgi.jaxrs.extension.name=*)" + filter + ")";
    }

    private OSGi<?> waitForExtensionDependencies(
        ServiceReference<?> serviceReference, OSGi<?> program) {

        String[] extensionDependencies = canonicalize(
            serviceReference.getProperty("osgi.jaxrs.extension.select"));

        for (String extensionDependency : extensionDependencies) {
            program =
                serviceReferences(buildExtensionFilter(extensionDependency)).
                then(program);
        }

        return program;
    }

    private <T> OSGi<?> safeRegisterEndpoint(
        ServiceReference<T> ref, CXFJaxRsServiceRegistrator registrator) {

        return
            bundleContext().flatMap(bundleContext ->
            serviceObjects(ref).flatMap(service ->
            registerEndpoint(ref, registrator, service).
                flatMap(serviceInformation ->
            onClose(
                () -> unregisterEndpoint(registrator, serviceInformation)))));
    }

    private <T> OSGi<ServiceInformation> registerEndpoint(
        ServiceReference<?> ref,
        CXFJaxRsServiceRegistrator registrator,
        ServiceObjects<T> serviceObjects) {

        Thread thread = Thread.currentThread();
        ClassLoader contextClassLoader = thread.getContextClassLoader();
        ClassLoader classLoader = ref.getBundle().adapt(BundleWiring.class).
            getClassLoader();
        Object resourceBaseObject = ref.getProperty("osgi.jaxrs.resource.base");

        ResourceProvider resourceProvider = getResourceProvider(serviceObjects);

        String resourceBase;

        if (resourceBaseObject == null) {
            resourceBase = "";
        }
        else {
            resourceBase = resourceBaseObject.toString();
        }
        try {
            thread.setContextClassLoader(classLoader);
            ServiceInformation serviceInformation = new ServiceInformation(
                resourceBase, resourceProvider);
            registrator.add(serviceInformation);
            return just(serviceInformation);
        }
        finally {
            thread.setContextClassLoader(contextClassLoader);
        }
    }

    private <T> ResourceProvider getResourceProvider(
        ServiceObjects<T> serviceObjects) {

        ResourceProvider resourceProvider;
        T service = serviceObjects.getService();
        Class<?> serviceClass = service.getClass();

        resourceProvider = new ResourceProvider() {

            @Override
            public Object getInstance(Message m) {
                return serviceObjects.getService();
            }

            @Override
            public void releaseInstance(Message m, Object o) {
                serviceObjects.ungetService((T)o);
            }

            @Override
            public Class<?> getResourceClass() {
                return serviceClass;
            }

            @Override
            public boolean isSingleton() {
                return false;
            }
        };

        serviceObjects.ungetService(service);
        return resourceProvider;
    }

    private void unregisterEndpoint(
        CXFJaxRsServiceRegistrator registrator,
        ServiceInformation serviceInformation) {

        registrator.remove(serviceInformation);
    }

    private ServiceRegistration<Servlet> registerCXFServletService(Bus bus) {
        Dictionary<String, Object> properties = new Hashtable<>();
        properties.put(HTTP_WHITEBOARD_CONTEXT_SELECT,
            "(" + HTTP_WHITEBOARD_CONTEXT_NAME + "=" + 
                HTTP_WHITEBOARD_DEFAULT_CONTEXT_NAME + ")");
        properties.put(HTTP_WHITEBOARD_SERVLET_PATTERN, "/*");
        properties.put(Constants.SERVICE_RANKING, -1);
        CXFNonSpringServlet cxfNonSpringServlet = createCXFServlet(bus);
        return _bundleContext.registerService(
            Servlet.class, cxfNonSpringServlet, properties);
    }

    private CXFNonSpringServlet createCXFServlet(Bus bus) {
        CXFNonSpringServlet cxfNonSpringServlet = new CXFNonSpringServlet();
        cxfNonSpringServlet.setBus(bus);
        return cxfNonSpringServlet;
    }

    private String getExtensionFilter() {
        return "(osgi.jaxrs.extension.name=*)";
    }

    private String getApplicationFilter() {
        return "(osgi.jaxrs.application.base=*)";
    }

    private String getSingletonsFilter() {
        return "(osgi.jaxrs.resource.base=*)";
    }
    
    @Override
    public void stop(BundleContext context) throws Exception {
        _applicationSingletonsResult.close();
        _applicationsResult.close();
        _extensionsResult.close();
        _singletonsResult.close();
    }

}
