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

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Dictionary;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.commons.collections4.BidiMap;
import org.apache.commons.collections4.bidimap.TreeBidiMap;
import org.apache.sling.api.resource.ResourceDecorator;
import org.apache.sling.api.resource.ResourceResolverFactory;
import org.apache.sling.api.resource.path.Path;
import org.apache.sling.api.resource.runtime.RuntimeService;
import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
import org.apache.sling.resourceresolver.impl.mapping.MapEntries;
import org.apache.sling.resourceresolver.impl.mapping.Mapping;
import org.apache.sling.resourceresolver.impl.observation.ResourceChangeListenerWhiteboard;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker;
import org.apache.sling.resourceresolver.impl.providers.ResourceProviderTracker.ChangeListener;
import org.apache.sling.resourceresolver.impl.providers.RuntimeServiceImpl;
import org.apache.sling.serviceusermapping.ServiceUserMapper;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.Constants;
import org.osgi.framework.ServiceFactory;
import org.osgi.framework.ServiceRegistration;
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.Modified;
import org.osgi.service.component.annotations.Reference;
import org.osgi.service.component.annotations.ReferenceCardinality;
import org.osgi.service.component.annotations.ReferencePolicy;
import org.osgi.service.event.EventAdmin;
import org.osgi.service.metatype.annotations.Designate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>ResourceResolverFactoryActivator/code> keeps track of required services for the
 * resource resolver factory.
 * One all required providers and provider factories are available a resource resolver factory
 * is registered.
 *
 */
@Designate(ocd = ResourceResolverFactoryConfig.class)
@Component(name = "org.apache.sling.jcr.resource.internal.JcrResourceResolverFactoryImpl")
public class ResourceResolverFactoryActivator {


    private static final class FactoryRegistration {
        /** Registration .*/
        public volatile ServiceRegistration<ResourceResolverFactory> factoryRegistration;

        /** Runtime registration. */
        public volatile ServiceRegistration<RuntimeService> runtimeRegistration;

        public volatile CommonResourceResolverFactoryImpl commonFactory;
    }


    /** Logger. */
    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    /** Tracker for the resource decorators. */
    private final ResourceDecoratorTracker resourceDecoratorTracker = new ResourceDecoratorTracker();

    /** all mappings */
    private volatile Mapping[] mappings;

    /** The fake URLs */
    private volatile BidiMap virtualURLMap;

    /** the search path for ResourceResolver.getResource(String) */
    private volatile List<String> searchPath = Collections.emptyList();

    /** the root location of the /etc/map entries */
    private volatile String mapRoot;

    private volatile String mapRootPrefix;

    /** Event admin. */
    @Reference
    EventAdmin eventAdmin;

    /** Service User Mapper */
    @Reference
    ServiceUserMapper serviceUserMapper;

    @Reference
    ResourceAccessSecurityTracker resourceAccessSecurityTracker;

    volatile ResourceProviderTracker resourceProviderTracker;

    volatile ResourceChangeListenerWhiteboard changeListenerWhiteboard;

    /** Bundle Context */
    private volatile BundleContext bundleContext;

    private volatile ResourceResolverFactoryConfig config = DEFAULT_CONFIG;

    /** Vanity path whitelist */
    private volatile String[] vanityPathWhiteList;

    /** Vanity path blacklist */
    private volatile String[] vanityPathBlackList;

    /** Observation paths */
    private volatile Path[] observationPaths;

    private final FactoryPreconditions preconds = new FactoryPreconditions();

    /** Factory registration. */
    private volatile FactoryRegistration factoryRegistration;

    /**
     * Get the resource decorator tracker.
     */
    public ResourceDecoratorTracker getResourceDecoratorTracker() {
        return this.resourceDecoratorTracker;
    }

    public ResourceAccessSecurityTracker getResourceAccessSecurityTracker() {
        return this.resourceAccessSecurityTracker;
    }

    public EventAdmin getEventAdmin() {
        return this.eventAdmin;
    }

    /**
     * This method is called from {@link MapEntries}
     */
    public BidiMap getVirtualURLMap() {
        return virtualURLMap;
    }

    /**
     * This method is called from {@link MapEntries}
     */
    public Mapping[] getMappings() {
        return mappings;
    }

    public List<String> getSearchPath() {
        return searchPath;
    }

    public boolean isMangleNamespacePrefixes() {
        return config.resource_resolver_manglenamespaces();

    }

    public String getMapRoot() {
        return mapRoot;
    }

    public boolean isMapConfiguration(String path) {
        return path.equals(this.mapRoot)
               || path.startsWith(this.mapRootPrefix);
    }

    public int getDefaultVanityPathRedirectStatus() {
        return config.resource_resolver_default_vanity_redirect_status();
    }

    public boolean isVanityPathEnabled() {
        return this.config.resource_resolver_enable_vanitypath();
    }

    public boolean isOptimizeAliasResolutionEnabled() {
        return this.config.resource_resolver_optimize_alias_resolution();
    }

    public boolean isLogUnclosedResourceResolvers() {
        return this.config.resource_resolver_log_unclosed();
    }

    public String[] getVanityPathWhiteList() {
        return this.vanityPathWhiteList;
    }

    public String[] getVanityPathBlackList() {
        return this.vanityPathBlackList;
    }

    public boolean hasVanityPathPrecedence() {
        return this.config.resource_resolver_vanity_precedence();
    }

    public long getMaxCachedVanityPathEntries() {
        return this.config.resource_resolver_vanitypath_maxEntries();
    }

    public boolean isMaxCachedVanityPathEntriesStartup() {
        return this.config.resource_resolver_vanitypath_maxEntries_startup();
    }

    public int getVanityBloomFilterMaxBytes() {
        return this.config.resource_resolver_vanitypath_bloomfilter_maxBytes();
    }

    public boolean shouldLogResourceResolverClosing() {
        return this.config.resource_resolver_log_closing();
    }

    public Path[] getObservationPaths() {
        return this.observationPaths;
    }

    // ---------- SCR Integration ---------------------------------------------

    /**
     * Activates this component (called by SCR before)
     */
    @Activate
    protected void activate(final BundleContext bundleContext, final ResourceResolverFactoryConfig config) {
        this.bundleContext = bundleContext;
        this.config = config;

        final BidiMap virtuals = new TreeBidiMap();
        for (int i = 0; config.resource_resolver_virtual() != null && i < config.resource_resolver_virtual().length; i++) {
            final String[] parts = Mapping.split(config.resource_resolver_virtual()[i]);
            virtuals.put(parts[0], parts[2]);
        }
        virtualURLMap = virtuals;

        final List<Mapping> maps = new ArrayList<>();
        for (int i = 0; config.resource_resolver_mapping() != null && i < config.resource_resolver_mapping().length; i++) {
            maps.add(new Mapping(config.resource_resolver_mapping()[i]));
        }
        final Mapping[] tmp = maps.toArray(new Mapping[maps.size()]);

        // check whether direct mappings are allowed
        if (config.resource_resolver_allowDirect()) {
            final Mapping[] tmp2 = new Mapping[tmp.length + 1];
            tmp2[0] = Mapping.DIRECT;
            System.arraycopy(tmp, 0, tmp2, 1, tmp.length);
            mappings = tmp2;
        } else {
            mappings = tmp;
        }

        // from configuration if available
        final List<String> searchPathList = new ArrayList<>();
        if (config.resource_resolver_searchpath() != null && config.resource_resolver_searchpath().length > 0) {
            for(String path : config.resource_resolver_searchpath()) {
                // ensure leading slash
                if (!path.startsWith("/")) {
                    path = "/".concat(path);
                }
                // ensure trailing slash
                if (!path.endsWith("/")) {
                    path = path.concat("/");
                }
                searchPathList.add(path);
            }
        }
        if (searchPathList.isEmpty()) {
            searchPathList.add("/");
        }
        this.searchPath = Collections.unmodifiableList(searchPathList);

        // the root of the resolver mappings
        mapRoot = config.resource_resolver_map_location();
        mapRootPrefix = mapRoot + '/';

        final String[] paths = config.resource_resolver_map_observation();
        this.observationPaths = new Path[paths.length];
        for(int i=0;i<paths.length;i++) {
            this.observationPaths[i] = new Path(paths[i]);
        }

        // vanity path white list
        this.vanityPathWhiteList = null;
        String[] vanityPathPrefixes = config.resource_resolver_vanitypath_whitelist();
        if ( vanityPathPrefixes != null ) {
            final List<String> prefixList = new ArrayList<>();
            for(final String value : vanityPathPrefixes) {
                if ( value.trim().length() > 0 ) {
                    if ( value.trim().endsWith("/") ) {
                        prefixList.add(value.trim());
                    } else {
                        prefixList.add(value.trim() + "/");
                    }
                }
            }
            if ( prefixList.size() > 0 ) {
                this.vanityPathWhiteList = prefixList.toArray(new String[prefixList.size()]);
            }
        }
        // vanity path black list
        this.vanityPathBlackList = null;
        vanityPathPrefixes = config.resource_resolver_vanitypath_blacklist();
        if ( vanityPathPrefixes != null ) {
            final List<String> prefixList = new ArrayList<>();
            for(final String value : vanityPathPrefixes) {
                if ( value.trim().length() > 0 ) {
                    if ( value.trim().endsWith("/") ) {
                        prefixList.add(value.trim());
                    } else {
                        prefixList.add(value.trim() + "/");
                    }
                }
            }
            if ( prefixList.size() > 0 ) {
                this.vanityPathBlackList = prefixList.toArray(new String[prefixList.size()]);
            }
        }

        // check for required property
        Set<String> requiredResourceProvidersLegacy = getStringSet(config.resource_resolver_required_providers());
        Set<String> requiredResourceProviderNames = getStringSet(config.resource_resolver_required_providernames());

        boolean hasLegacyRequiredProvider = false;
        if ( requiredResourceProvidersLegacy != null ) {
            hasLegacyRequiredProvider = requiredResourceProvidersLegacy.remove(ResourceResolverFactoryConfig.LEGACY_REQUIRED_PROVIDER_PID);
            if ( !requiredResourceProvidersLegacy.isEmpty() ) {
                logger.error("ResourceResolverFactory is using deprecated required providers configuration (resource.resolver.required.providers" +
                        "). Please change to use the property resource.resolver.required.providernames for values: " + requiredResourceProvidersLegacy);
            } else {
            	requiredResourceProvidersLegacy = null;
            }
        }
        if ( hasLegacyRequiredProvider ) {
            final boolean hasRequiredProvider;
        	if ( requiredResourceProviderNames != null ) {
        		hasRequiredProvider = !requiredResourceProviderNames.add(ResourceResolverFactoryConfig.REQUIRED_PROVIDER_NAME);
        	} else {
        		hasRequiredProvider = false;
        		requiredResourceProviderNames = Collections.singleton(ResourceResolverFactoryConfig.REQUIRED_PROVIDER_NAME);
        	}
        	if ( hasRequiredProvider ) {
                logger.warn("ResourceResolverFactory is using deprecated required providers configuration (resource.resolver.required.providers" +
                        ") with value '" + ResourceResolverFactoryConfig.LEGACY_REQUIRED_PROVIDER_PID + ". Please remove this configuration property. " +
                        ResourceResolverFactoryConfig.REQUIRED_PROVIDER_NAME + " is already contained in the property resource.resolver.required.providernames.");
        	} else {
                logger.warn("ResourceResolverFactory is using deprecated required providers configuration (resource.resolver.required.providers" +
                        ") with value '" + ResourceResolverFactoryConfig.LEGACY_REQUIRED_PROVIDER_PID + ". Please remove this configuration property and add " +
                        ResourceResolverFactoryConfig.REQUIRED_PROVIDER_NAME + " to the property resource.resolver.required.providernames.");
        	}
        }

        // for testing: if we run unit test, both trackers are set from the outside
        if ( this.resourceProviderTracker == null ) {
            this.resourceProviderTracker = new ResourceProviderTracker();
            this.changeListenerWhiteboard = new ResourceChangeListenerWhiteboard();
            this.preconds.activate(this.bundleContext,
            		requiredResourceProvidersLegacy,
            		requiredResourceProviderNames,
            		resourceProviderTracker);
            this.changeListenerWhiteboard.activate(this.bundleContext,
                this.resourceProviderTracker, searchPath);
            this.resourceProviderTracker.activate(this.bundleContext,
                    this.eventAdmin,
                    new ChangeListener() {

                        @Override
                        public void providerAdded() {
                            if ( factoryRegistration == null ) {
                                checkFactoryPreconditions(null, null);
                            }

                        }

                        @Override
                        public void providerRemoved(final String name, final String pid, final boolean stateful, final boolean isUsed) {
                            if ( factoryRegistration != null ) {
                                if ( isUsed && (stateful || config.resource_resolver_providerhandling_paranoid()) ) {
                                    unregisterFactory();
                                }
                                checkFactoryPreconditions(name, pid);
                            }
                        }
                    });
        } else {
            this.preconds.activate(this.bundleContext,
            		requiredResourceProvidersLegacy,
            		requiredResourceProviderNames,
            		resourceProviderTracker);
            this.checkFactoryPreconditions(null, null);
         }
    }

    /**
     * Modifies this component (called by SCR to update this component)
     */
    @Modified
    protected void modified(final BundleContext bundleContext, final ResourceResolverFactoryConfig config) {
        this.deactivate();
        this.activate(bundleContext, config);
    }

    /**
     * Deactivates this component (called by SCR to take out of service)
     */
    @Deactivate
    protected void deactivate() {
        this.unregisterFactory();

        this.bundleContext = null;
        this.config = DEFAULT_CONFIG;
        this.changeListenerWhiteboard.deactivate();
        this.changeListenerWhiteboard = null;
        this.resourceProviderTracker.deactivate();
        this.resourceProviderTracker = null;

        this.preconds.deactivate();
        this.resourceDecoratorTracker.close();

        // this is just a sanity call to make sure that unregister
        // in the case that a registration happened again
        // while deactivation
        this.unregisterFactory();
    }

    /**
     * Unregister the factory (if registered)
     * This method might be called concurrently from deactivate and the
     * background thread, therefore we need to synchronize.
     */
    private void unregisterFactory() {
        FactoryRegistration local = null;
        synchronized ( this ) {
            if ( this.factoryRegistration != null ) {
                local = this.factoryRegistration;
                this.factoryRegistration = null;
            }
        }
        this.unregisterFactory(local);
    }

    /**
     * Unregister the provided factory
     */
    private void unregisterFactory(final FactoryRegistration local) {
        if ( local != null ) {
            if ( local.factoryRegistration != null ) {
                local.factoryRegistration.unregister();
            }
            if ( local.runtimeRegistration != null ) {
                local.runtimeRegistration.unregister();
            }
            if ( local.commonFactory != null ) {
                local.commonFactory.deactivate();
            }
        }
    }

    /**
     * Try to register the factory.
     */
    private void registerFactory(final BundleContext localContext) {
        final FactoryRegistration local = new FactoryRegistration();

        if ( localContext != null ) {
            // activate and register factory
            final Dictionary<String, Object> serviceProps = new Hashtable<>();
            serviceProps.put(Constants.SERVICE_VENDOR, "The Apache Software Foundation");
            serviceProps.put(Constants.SERVICE_DESCRIPTION, "Apache Sling Resource Resolver Factory");

            local.commonFactory = new CommonResourceResolverFactoryImpl(this);
            local.commonFactory.activate(localContext);
            local.factoryRegistration = localContext.registerService(
                ResourceResolverFactory.class, new ServiceFactory<ResourceResolverFactory>() {

                    @Override
                    public ResourceResolverFactory getService(final Bundle bundle, final ServiceRegistration<ResourceResolverFactory> registration) {
                        if ( ResourceResolverFactoryActivator.this.bundleContext == null ) {
                            return null;
                        }
                        final ResourceResolverFactoryImpl r = new ResourceResolverFactoryImpl(
                                local.commonFactory, bundle,
                            ResourceResolverFactoryActivator.this.serviceUserMapper);
                        return r;
                    }

                    @Override
                    public void ungetService(final Bundle bundle, final ServiceRegistration<ResourceResolverFactory> registration, final ResourceResolverFactory service) {
                        // nothing to do
                    }
                }, serviceProps);

            local.runtimeRegistration = localContext.registerService(RuntimeService.class,
                    this.getRuntimeService(), null);

            this.factoryRegistration = local;
        }
    }

    /**
     * Get the runtime service
     * @return The runtime service
     */
    public RuntimeService getRuntimeService() {
        return new RuntimeServiceImpl(this.resourceProviderTracker);
    }

    public ServiceUserMapper getServiceUserMapper() {
    	return this.serviceUserMapper;
    }

    public BundleContext getBundleContext() {
    	return this.bundleContext;
    }

    /**
     * Check the preconditions and if it changed, either register factory or unregister
     */
    private void checkFactoryPreconditions(final String unavailableName, final String unavailableServicePid) {
        final BundleContext localContext = this.bundleContext;
        if ( localContext != null ) {
            final boolean result = this.preconds.checkPreconditions(unavailableName, unavailableServicePid);
            if ( result && this.factoryRegistration == null ) {
                // check system bundle state - if stopping, don't register new factory
                final Bundle systemBundle = localContext.getBundle(Constants.SYSTEM_BUNDLE_LOCATION);
                if ( systemBundle != null && systemBundle.getState() != Bundle.STOPPING ) {
                    boolean create = true;
                    synchronized ( this ) {
                        if ( this.factoryRegistration == null ) {
                            this.factoryRegistration = new FactoryRegistration();
                        } else {
                            create = false;
                        }
                    }
                    if ( create ) {
                        this.registerFactory(localContext);
                    }
                }
            } else if ( !result && this.factoryRegistration != null ) {
                this.unregisterFactory();
            }
        }
    }

    /**
     * Bind a resource decorator.
     */
    @Reference(service = ResourceDecorator.class, cardinality = ReferenceCardinality.MULTIPLE, policy = ReferencePolicy.DYNAMIC)
    protected void bindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
        this.resourceDecoratorTracker.bindResourceDecorator(decorator, props);
    }

    /**
     * Unbind a resource decorator.
     */
    protected void unbindResourceDecorator(final ResourceDecorator decorator, final Map<String, Object> props) {
        this.resourceDecoratorTracker.unbindResourceDecorator(decorator, props);
    }

    /**
     * Get the resource provider tracker
     * @return The tracker
     */
    public ResourceProviderTracker getResourceProviderTracker() {
        return resourceProviderTracker;
    }

    /**
     * Utility method to create a set out of a string array
     */
    private Set<String> getStringSet(final String[] values) {
    	if ( values == null || values.length == 0 ) {
    		return null;
    	}
    	final Set<String> set = new HashSet<>();
    	for(final String val : values) {
    		if ( val != null && !val.trim().isEmpty() ) {
    			set.add(val.trim());
    		}
    	}
    	return set.isEmpty() ? null : set;
    }

    public static ResourceResolverFactoryConfig DEFAULT_CONFIG;

    static {
       final InvocationHandler handler = new InvocationHandler() {

            @Override
            public Object invoke(final Object obj, final Method calledMethod, final Object[] args)
            throws Throwable {
                if ( calledMethod.getDeclaringClass().isAssignableFrom(ResourceResolverFactoryConfig.class) ) {
                   return calledMethod.getDefaultValue();
                }
                if ( calledMethod.getDeclaringClass() == Object.class ) {
                    if ( calledMethod.getName().equals("toString") && (args == null || args.length == 0) ) {
                        return "Generated @" + ResourceResolverFactoryConfig.class.getName() + " instance";
                    }
                    if ( calledMethod.getName().equals("hashCode") && (args == null || args.length == 0) ) {
                        return this.hashCode();
                    }
                    if ( calledMethod.getName().equals("equals") && args != null && args.length == 1 ) {
                        return Boolean.FALSE;
                    }
                }
                throw new InternalError("unexpected method dispatched: " + calledMethod);
            }
        };
        DEFAULT_CONFIG = (ResourceResolverFactoryConfig) Proxy.newProxyInstance(ResourceResolverFactoryConfig.class.getClassLoader(),
                new Class[] { ResourceResolverFactoryConfig.class },
                handler);
    }
}
