/*
 * 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.unomi.rest;

import com.fasterxml.jackson.jaxrs.json.JacksonJaxbJsonProvider;
import org.apache.cxf.Bus;
import org.apache.cxf.BusFactory;
import org.apache.cxf.endpoint.Server;
import org.apache.cxf.feature.LoggingFeature;
import org.apache.cxf.jaxrs.JAXRSServerFactoryBean;
import org.apache.cxf.jaxrs.openapi.OpenApiCustomizer;
import org.apache.cxf.jaxrs.openapi.OpenApiFeature;
import org.apache.cxf.jaxrs.security.JAASAuthenticationFilter;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Filter;
import org.osgi.framework.ServiceReference;
import org.osgi.service.component.ComponentContext;
import org.osgi.service.component.annotations.Activate;
import org.osgi.service.component.annotations.Component;
import org.osgi.service.component.annotations.Deactivate;
import org.osgi.service.component.annotations.Reference;
import org.osgi.util.tracker.ServiceTracker;
import org.osgi.util.tracker.ServiceTrackerCustomizer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.ws.rs.ext.ExceptionMapper;
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;

@Component
public class RestServer {

    private static final Logger logger = LoggerFactory.getLogger(RestServer.class.getName());

    private Server server;
    private BundleContext bundleContext;
    private ServiceTracker jaxRSServiceTracker;
    private List<ExceptionMapper> exceptionMappers = new ArrayList<>();
    private long timeOfLastUpdate = System.currentTimeMillis();
    private Timer refreshTimer = null;
    private long startupDelay = 1000L;

    final List<Object> serviceBeans = new CopyOnWriteArrayList<>();

    @Reference
    public void addExceptionMapper(ExceptionMapper exceptionMapper) {
        this.exceptionMappers.add(exceptionMapper);
        timeOfLastUpdate = System.currentTimeMillis();
        refreshServer();
    }

    public void removeExceptionMapper(ExceptionMapper exceptionMapper) {
        this.exceptionMappers.remove(exceptionMapper);
        timeOfLastUpdate = System.currentTimeMillis();
        refreshServer();
    }

    @Activate
    public void activate(ComponentContext componentContext) throws Exception {
        this.bundleContext = componentContext.getBundleContext();

        Filter filter = bundleContext.createFilter("(osgi.jaxrs.resource=true)");
        jaxRSServiceTracker = new ServiceTracker(bundleContext, filter, new ServiceTrackerCustomizer() {
            @Override
            public Object addingService(ServiceReference reference) {
                Object serviceBean = bundleContext.getService(reference);
                logger.info("Registering JAX RS service " + serviceBean.getClass().getName());
                serviceBeans.add(serviceBean);
                timeOfLastUpdate = System.currentTimeMillis();
                refreshServer();
                return serviceBean;
            }

            @Override
            public void modifiedService(ServiceReference reference, Object service) {
                logger.info("Refreshing JAX RS server because service " + service.getClass().getName() + " was modified.");
                timeOfLastUpdate = System.currentTimeMillis();
                refreshServer();
            }

            @Override
            public void removedService(ServiceReference reference, Object service) {
                Object serviceBean = bundleContext.getService(reference);
                logger.info("Removing JAX RS service " + serviceBean.getClass().getName());
                serviceBeans.remove(serviceBean);
                timeOfLastUpdate = System.currentTimeMillis();
                refreshServer();
            }
        });
        jaxRSServiceTracker.open();
    }

    @Deactivate
    public void deactivate() throws Exception {
        jaxRSServiceTracker.close();
        if (server != null) {
            server.destroy();
        }
    }

    private synchronized void refreshServer() {
        long now = System.currentTimeMillis();
        logger.info("Time (millis) since last update: {}", now - timeOfLastUpdate);
        if (now - timeOfLastUpdate < startupDelay) {
            if (refreshTimer != null) {
                return;
            }
            TimerTask task = new TimerTask() {
                public void run() {
                    refreshTimer = null;
                    refreshServer();
                    logger.info("Refreshed server task performed on: " + new Date() +
                            " Thread's name: " + Thread.currentThread().getName());
                }
            };
            refreshTimer = new Timer("Timer-Refresh-REST-API");

            refreshTimer.schedule(task, startupDelay);
            return;
        }

        if (server != null) {
            logger.info("Shutting down JAX RS Endpoint... ");
            server.destroy();
        }

        final OpenApiFeature openApiFeature = new OpenApiFeature();
        openApiFeature.setContactEmail("dev@unomi.apache.org");
        openApiFeature.setLicense("Apache 2.0 License");
        openApiFeature.setLicenseUrl("http://www.apache.org/licenses/LICENSE-2.0.html");
        openApiFeature.setScan(false);
        openApiFeature.setUseContextBasedConfig(true);        //Set<String> resourceClasses = serviceBeans.stream().map(service -> service.getClass().getName()).collect(toSet());
        OpenApiCustomizer customizer = new OpenApiCustomizer();
        customizer.setDynamicBasePath(true);
        openApiFeature.setCustomizer(customizer);

        JAXRSServerFactoryBean jaxrsServerFactoryBean = new JAXRSServerFactoryBean();
        jaxrsServerFactoryBean.setAddress("/");
        Bus bus = BusFactory.getDefaultBus();
        // bus.getFeatures().add(new LoggingFeature());
        bus.getFeatures().add(new LoggingFeature());
        bus.getFeatures().add(new org.apache.cxf.metrics.MetricsFeature());
        jaxrsServerFactoryBean.setBus(bus);
        jaxrsServerFactoryBean.setProvider(
                new JacksonJaxbJsonProvider(
                        new org.apache.unomi.persistence.spi.CustomObjectMapper(),
                        JacksonJaxbJsonProvider.DEFAULT_ANNOTATIONS));
        jaxrsServerFactoryBean.setProvider(new org.apache.cxf.rs.security.cors.CrossOriginResourceSharingFilter());
        JAASAuthenticationFilter jaasFilter = new org.apache.cxf.jaxrs.security.JAASAuthenticationFilter();
        jaasFilter.setContextName("karaf");
        jaasFilter.setRoleClassifier("ROLE_");
        jaasFilter.setRealmName("cxs");
        jaxrsServerFactoryBean.setProvider(jaasFilter);
        for (ExceptionMapper exceptionMapper : exceptionMappers) {
            jaxrsServerFactoryBean.setProvider(exceptionMapper);
        }
        jaxrsServerFactoryBean.setServiceBeans(serviceBeans);
        jaxrsServerFactoryBean.getFeatures().add(openApiFeature);
        if (serviceBeans.size() > 0) {
            logger.info("Starting JAX RS Endpoint...");
            server = jaxrsServerFactoryBean.create();
        }
    }

}
