/*
 * 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.sling.rewriter.impl;

import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.sling.commons.osgi.OsgiUtil;
import org.apache.sling.rewriter.Generator;
import org.apache.sling.rewriter.GeneratorFactory;
import org.apache.sling.rewriter.ProcessingContext;
import org.apache.sling.rewriter.Processor;
import org.apache.sling.rewriter.ProcessorConfiguration;
import org.apache.sling.rewriter.ProcessorFactory;
import org.apache.sling.rewriter.Serializer;
import org.apache.sling.rewriter.SerializerFactory;
import org.apache.sling.rewriter.Transformer;
import org.apache.sling.rewriter.TransformerFactory;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.InvalidSyntaxException;
import org.osgi.framework.ServiceReference;
import org.osgi.util.tracker.ServiceTracker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * This is an utility class for accessing the various pipeline components.
 * it also acts like a cache for the factories.
 */
public class FactoryCache {

    /** The required property containing the component type. */
    private static final String PROPERTY_TYPE = "pipeline.type";

    /** The optional property for the pipeline mode (global) */
    private static final String PROPERTY_MODE = "pipeline.mode";

    /** The global mode. */
    private static final String MODE_GLOBAL = "global";

    /** The optional property for the paths the component should apply to */
    private static final String PROPERTY_PATHS = "pipeline.paths";

    /** The optional property for the extensions the component should apply to */
    private static final String PROPERTY_EXTENSIONS = "pipeline.extensions";

    /** The optional property for the content types the component should apply to */
    private static final String PROPERTY_CONTENT_TYPES = "pipeline.contentTypes";

    /** The optional property for the selectors the component should apply to */
    private static final String PROPERTY_SELECTORS = "pipeline.selectors";

    /** The optional property for the resource types the component should apply to */
    private static final String PROPERTY_RESOURCE_TYPES = "pipeline.resourceTypes";

    /** The logger. */
    private static final Logger LOGGER = LoggerFactory.getLogger(FactoryCache.class);

    /** The tracker for generator factories. */
    private final HashingServiceTrackerCustomizer<GeneratorFactory> generatorTracker;

    /** The tracker for serializers factories. */
    private final HashingServiceTrackerCustomizer<SerializerFactory> serializerTracker;

    /** The tracker for transformer factories. */
    private final TransformerFactoryServiceTracker<TransformerFactory> transformerTracker;

    /** The tracker for processor factories. */
    private final HashingServiceTrackerCustomizer<ProcessorFactory> processorTracker;

    public FactoryCache(final BundleContext context)
    throws InvalidSyntaxException {
        this.generatorTracker = new HashingServiceTrackerCustomizer<GeneratorFactory>(context,
                GeneratorFactory.class.getName());
        this.serializerTracker = new HashingServiceTrackerCustomizer<SerializerFactory>(context,
                SerializerFactory.class.getName());
        this.transformerTracker = new TransformerFactoryServiceTracker<TransformerFactory>(context,
                TransformerFactory.class.getName());
        this.processorTracker = new HashingServiceTrackerCustomizer<ProcessorFactory>(context,
                ProcessorFactory.class.getName());
    }

    /**
     * Start tracking
     */
    public void start() {
        this.generatorTracker.open();
        this.serializerTracker.open();
        this.transformerTracker.open();
        this.processorTracker.open();
    }

    /**
     * Stop tracking
     */
    public void stop() {
        this.generatorTracker.close();
        this.serializerTracker.close();
        this.transformerTracker.close();
        this.processorTracker.close();
    }

    /**
     * Get the generator of the given type.
     * @param type The generator type.
     * @return The generator or null if the generator is not available.
     */
    public Generator getGenerator(final String type) {
        final GeneratorFactory factory = this.generatorTracker.getFactory(type);
        if ( factory == null ) {
            LOGGER.debug("Requested generator factory for type '{}' not found.", type);
            return null;
        }
        return factory.createGenerator();
    }

    /**
     * Get the serializer of the given type.
     * @param type The serializer type.
     * @return The serializer or null if the serializer is not available.
     */
    public Serializer getSerializer(final String type) {
        final SerializerFactory factory = this.serializerTracker.getFactory(type);
        if ( factory == null ) {
            LOGGER.debug("Requested serializer factory for type '{}' not found.", type);
            return null;
        }
        return factory.createSerializer();
    }

    /**
     * Get the transformer of the given type.
     * @param type The transformer type.
     * @return The transformer or null if the transformer is not available.
     */
    public Transformer getTransformer(final String type) {
        final TransformerFactory factory = this.transformerTracker.getFactory(type);
        if ( factory == null ) {
            LOGGER.debug("Requested transformer factory for type '{}' not found.", type);
            return null;
        }
        return factory.createTransformer();
    }

    /**
     * Get the processor of the given type.
     * @param type The processor type.
     * @return The processor or null if the processor is not available.
     */
    public Processor getProcessor(final String type) {
        final ProcessorFactory factory = this.processorTracker.getFactory(type);
        if ( factory == null ) {
            LOGGER.debug("Requested processor factory for type '{}' not found.", type);
            return null;
        }
        return factory.createProcessor();
    }

    private static final Transformer[] EMPTY_ARRAY = new Transformer[0];
    private static final Transformer[][] EMPTY_DOUBLE_ARRAY = new Transformer[][] {EMPTY_ARRAY, EMPTY_ARRAY};

    /**
     * Lookup all global transformers that apply to the current request and return
     * the transformer instances in two arrays.
     * The first array contains all pre transformers and the second one contains
     * all post transformers.
     * @param context The current processing context.
     */
    public Transformer[][] getGlobalTransformers(final ProcessingContext context) {
        final TransformerFactory[][] factories = this.transformerTracker.getGlobalTransformerFactories(context);
        return createTransformers(factories);
    }

    /**
     * Create new instances from the factories
     * @param factories The transformer factories
     * @return The transformer instances
     */
    private Transformer[][] createTransformers(final TransformerFactory[][] factories) {
        if ( factories == EMPTY_DOUBLE_ARRAY ) {
            return FactoryCache.EMPTY_DOUBLE_ARRAY;
        }
        final Transformer[][] transformers = new Transformer[2][];
        for(int arrayIndex = 0; arrayIndex < 2; arrayIndex++) {
            int count = factories[arrayIndex].length;
            for(final TransformerFactory factory : factories[arrayIndex]) {
                if ( factory == null ) count--;
            }
            if ( count == 0 ) {
                transformers[arrayIndex] = FactoryCache.EMPTY_ARRAY;
            } else {
                transformers[arrayIndex] = new Transformer[count];
                for(int i=0; i < factories[arrayIndex].length; i++) {
                    final TransformerFactory factory = factories[arrayIndex][i];
                    if ( factory != null ) {
                        transformers[arrayIndex][i] = factory.createTransformer();
                    }
                }
            }
        }

        return transformers;
    }

    /**
     * This service tracker stores all services into a hash map.
     */
    private static class HashingServiceTrackerCustomizer<T> extends ServiceTracker {

        /** The services hashed by their name property. */
        private final Map<String, T> services = new ConcurrentHashMap<String, T>();

        /** The bundle context. */
        protected final BundleContext context;

        public HashingServiceTrackerCustomizer(final BundleContext bc, final String serviceClassName) {
            super(bc, serviceClassName, null);
            this.context = bc;
        }

        public T getFactory(final String type) {
            return services.get(type);
        }

        private String getType(final ServiceReference ref) {
            final String type = (String) ref.getProperty(PROPERTY_TYPE);
            return type;
        }

        /**
         * @see org.osgi.util.tracker.ServiceTrackerCustomizer#addingService(org.osgi.framework.ServiceReference)
         */
        public Object addingService(final ServiceReference reference) {
            final String type = this.getType(reference);
            @SuppressWarnings("unchecked")
            final T factory = (type == null ? null : (T) this.context.getService(reference));
            if ( factory != null ) {
                if ( LOGGER.isDebugEnabled() ) {
                    LOGGER.debug("Found service {}, type={}.", factory, type);
                }
                this.services.put(type, factory);
            }
            return factory;
        }

        /**
         * @see org.osgi.util.tracker.ServiceTrackerCustomizer#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
         */
        public void removedService(final ServiceReference reference, final Object service) {
            final String type = this.getType(reference);
            if ( type != null ) {
                this.services.remove(type);
                this.context.ungetService(reference);
            }
        }
    }

    private static final class TransformerFactoryServiceTracker<T> extends HashingServiceTrackerCustomizer<T> {

        private String getMode(final ServiceReference ref) {
            final String mode = (String) ref.getProperty(PROPERTY_MODE);
            return mode;
        }

        private boolean isGlobal(final ServiceReference ref) {
            return MODE_GLOBAL.equalsIgnoreCase(this.getMode(ref));
        }

        public static final TransformerFactoryEntry[] EMPTY_ENTRY_ARRAY = new TransformerFactoryEntry[0];
        public static final TransformerFactoryEntry[][] EMPTY_DOUBLE_ENTRY_ARRAY = new TransformerFactoryEntry[][] {EMPTY_ENTRY_ARRAY, EMPTY_ENTRY_ARRAY};

        public static final TransformerFactory[] EMPTY_FACTORY_ARRAY = new TransformerFactory[0];
        public static final TransformerFactory[][] EMPTY_DOUBLE_FACTORY_ARRAY = new TransformerFactory[][] {EMPTY_FACTORY_ARRAY, EMPTY_FACTORY_ARRAY};

        private TransformerFactoryEntry[][] cached = EMPTY_DOUBLE_ENTRY_ARRAY;

        /** flag for cache. */
        private boolean cacheIsValid = true;

        public TransformerFactoryServiceTracker(final BundleContext bc, final String serviceClassName) {
            super(bc, serviceClassName);
        }

        /**
         * @see org.osgi.util.tracker.ServiceTracker#addingService(org.osgi.framework.ServiceReference)
         */
        public Object addingService(ServiceReference reference) {
            final boolean isGlobal = isGlobal(reference);
            if ( isGlobal ) {
                this.cacheIsValid = false;
            }
            Object obj = super.addingService(reference);
            if ( obj == null && isGlobal ) {
                obj = this.context.getService(reference);
            }
            return obj;
        }

        /**
         * @see org.osgi.util.tracker.ServiceTracker#removedService(org.osgi.framework.ServiceReference, java.lang.Object)
         */
        public void removedService(ServiceReference reference, Object service) {
            if ( isGlobal(reference) ) {
                this.cacheIsValid = false;
            }
            super.removedService(reference, service);
        }

        /**
         * Get all global transformer factories.
         * @return Two arrays of transformer factories
         */
        public TransformerFactoryEntry[][] getGlobalTransformerFactoryEntries() {
            if ( !this.cacheIsValid ) {
                synchronized ( this ) {
                    if ( !this.cacheIsValid ) {
                        final ServiceReference[] refs = this.getServiceReferences();
                        if ( refs == null || refs.length == 0 ) {
                            this.cached = EMPTY_DOUBLE_ENTRY_ARRAY;
                        } else {
                            Arrays.sort(refs, ServiceReferenceComparator.INSTANCE);

                            int preCount = 0;
                            int postCount = 0;
                            for(final ServiceReference ref : refs) {
                                if ( isGlobal(ref) ) {
                                    final Object r = ref.getProperty(Constants.SERVICE_RANKING);
                                    int ranking = (r instanceof Integer ? (Integer)r : 0);
                                    if ( ranking < 0 ) {
                                        preCount++;
                                    } else {
                                        postCount++;
                                    }
                                }
                            }
                            final TransformerFactoryEntry[][] globalFactories = new TransformerFactoryEntry[2][];
                            if ( preCount == 0 ) {
                                globalFactories[0] = EMPTY_ENTRY_ARRAY;
                            } else {
                                globalFactories[0] = new TransformerFactoryEntry[preCount];
                            }
                            if ( postCount == 0) {
                                globalFactories[1] = EMPTY_ENTRY_ARRAY;
                            } else {
                                globalFactories[1] = new TransformerFactoryEntry[postCount];
                            }
                            int index = 0;
                            for(final ServiceReference ref : refs) {
                                if ( isGlobal(ref) ) {
                                    if ( index < preCount ) {
                                        globalFactories[0][index] = new TransformerFactoryEntry((TransformerFactory) this.getService(ref), ref);
                                    } else {
                                        globalFactories[1][index - preCount] = new TransformerFactoryEntry((TransformerFactory) this.getService(ref), ref);
                                    }
                                    index++;
                                }
                            }
                            this.cached = globalFactories;
                        }
                    }
                    this.cacheIsValid = true;
                }
            }

            return this.cached;
        }

        /**
         * Get all global transformer factories that apply to the current request.
         * @param context The current processing context.
         * @return Two arrays containing the transformer factories.
         */
        public TransformerFactory[][] getGlobalTransformerFactories(final ProcessingContext context) {
            final TransformerFactoryEntry[][] globalFactoryEntries = this.getGlobalTransformerFactoryEntries();
            // quick check
            if ( globalFactoryEntries == EMPTY_DOUBLE_ENTRY_ARRAY ) {
                return EMPTY_DOUBLE_FACTORY_ARRAY;
            }
            final TransformerFactory[][] factories = new TransformerFactory[2][];
            for(int i=0; i<2; i++) {
                if ( globalFactoryEntries[i] == EMPTY_ENTRY_ARRAY ) {
                    factories[i] = EMPTY_FACTORY_ARRAY;
                } else {
                    factories[i] = new TransformerFactory[globalFactoryEntries[i].length];
                    for(int m=0; m<globalFactoryEntries[i].length; m++) {
                        final TransformerFactoryEntry entry = globalFactoryEntries[i][m];
                        if ( entry.match(context) ) {
                            factories[i][m] = entry.factory;
                        }
                    }
                }
            }
            return factories;
        }
    }

    /**
     * Comparator for service references.
     */
    private static final class ServiceReferenceComparator implements Comparator<ServiceReference> {
        public static ServiceReferenceComparator INSTANCE = new ServiceReferenceComparator();

        public int compare(ServiceReference o1, ServiceReference o2) {
            return o1.compareTo(o2);
        }
    }

    private static final class TransformerFactoryEntry {
        public final TransformerFactory factory;

        private final ProcessorConfiguration configuration;

        public TransformerFactoryEntry(final TransformerFactory factory, final ServiceReference ref) {
            this.factory = factory;
            final String[] paths = OsgiUtil.toStringArray(ref.getProperty(PROPERTY_PATHS), null);
            final String[] extensions = OsgiUtil.toStringArray(ref.getProperty(PROPERTY_EXTENSIONS), null);
            final String[] contentTypes = OsgiUtil.toStringArray(ref.getProperty(PROPERTY_CONTENT_TYPES), null);
            final String[] resourceTypes = OsgiUtil.toStringArray(ref.getProperty(PROPERTY_RESOURCE_TYPES), null);
            final String[] selectors = OsgiUtil.toStringArray(ref.getProperty(PROPERTY_SELECTORS), null);
            final boolean noCheckRequired = (paths == null || paths.length == 0) &&
                                   (extensions == null || extensions.length == 0) &&
                                   (contentTypes == null || contentTypes.length == 0) &&
                                   (resourceTypes == null || resourceTypes.length == 0) &&
                                   (selectors == null || selectors.length == 0);
            if ( !noCheckRequired ) {
                this.configuration = new ProcessorConfigurationImpl(contentTypes, paths, extensions, resourceTypes, selectors);
            } else {
                this.configuration = null;
            }
        }

        public boolean match(final ProcessingContext context) {
            if ( configuration == null ) {
                return true;
            }
            return configuration.match(context);
        }
    }
}
