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

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;

import javax.servlet.http.HttpServletRequest;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceUtil;
import org.apache.sling.api.resource.mapping.PathToUriMappingService;
import org.apache.sling.api.resource.mapping.ResourceMapper;
import org.apache.sling.api.uri.SlingUri;
import org.apache.sling.resourceresolver.impl.JcrNamespaceMangler;
import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
import org.apache.sling.resourceresolver.impl.helper.ResourceDecoratorTracker;
import org.apache.sling.resourceresolver.impl.helper.ResourceResolverControl;
import org.apache.sling.resourceresolver.impl.helper.URI;
import org.apache.sling.resourceresolver.impl.helper.URIException;
import org.apache.sling.resourceresolver.impl.params.ParsedParameters;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class ResourceMapperImpl implements ResourceMapper {
    
    private final Logger logger = LoggerFactory.getLogger(getClass());

    private final ResourceResolverImpl resolver;
    private final ResourceDecoratorTracker resourceDecorator;
    private final MapEntriesHandler mapEntries;
    private final boolean optimizedAliasResolutionEnabled;
    private final Object namespaceMangler;
    private final PathToUriMappingService pathToUriMappingService;

    public ResourceMapperImpl(ResourceResolverImpl resolver, ResourceDecoratorTracker resourceDecorator, 
            MapEntriesHandler mapEntries, boolean optimizedAliasResolutionEnabled, Object namespaceMangler,
            PathToUriMappingService pathToUriMappingService) {
        this.resolver = resolver;
        this.resourceDecorator = resourceDecorator;
        this.mapEntries = mapEntries;
        this.optimizedAliasResolutionEnabled = optimizedAliasResolutionEnabled;
        this.namespaceMangler = namespaceMangler;
        this.pathToUriMappingService = pathToUriMappingService;
    }

    @Override
    public String getMapping(String resourcePath) {
        return getMapping(resourcePath, null);
    }

    @Override
    public String getMapping(String resourcePath, HttpServletRequest request) {
        
        Collection<String> mappings = getAllMappings(resourcePath, request);
        if ( mappings.isEmpty() )
            return null;
        
        return mappings.iterator().next();
    }

    @Override
    public Collection<String> getAllMappings(String resourcePath) {
        return getAllMappings(resourcePath, null);
    }

    @Override
    public Collection<String> getAllMappings(String resourcePath, HttpServletRequest request) {
        
        resolver.checkClosed();
        
        // A note on the usage of the 'mappings' variable and the order of the results
        //
        // The API contract of the ResourceMapper does not specify the order in which the elements are returned
        // As an implementation detail however the getMapping method picks the first element of the return value
        // as the 'winner'.
        // 
        // Therefore we take care to add the entries in a very particular order, which preserves backwards 
        // compatibility with the existing implementation. Previously the order was
        //
        //   resource path → aliases → mapping (with aliases potentially being empty)
        //
        // To ensure we keep the same behaviour but expose all possible mappings, we now have the following
        // flow
        // 
        //  resource path → mapping
        //  resource path → aliases
        //  aliases → mappings
        //
        // After all are processed we reverse the order to preserve the logic of the old ResourceResolver.map() method (last
        // found wins) and also make sure that no duplicates are added.
        //
        // There is some room for improvement here by using a data structure that does not need reversing ( ArrayList
        // .add moves the elements every time ) or reversal of duplicates but since we will have a small number of 
        // entries ( <= 4 in case of single aliases) the time spent here should be negligible.
        
        List<String> mappings = new ArrayList<>();
        
        // 1. parse parameters
        
        // find a fragment or query
        int fragmentQueryMark = resourcePath.indexOf('#');
        if (fragmentQueryMark < 0) {
            fragmentQueryMark = resourcePath.indexOf('?');
        }

        // cut fragment or query off the resource path
        String mappedPath;
        final String fragmentQuery;
        if (fragmentQueryMark >= 0) {
            fragmentQuery = resourcePath.substring(fragmentQueryMark);
            mappedPath = resourcePath.substring(0, fragmentQueryMark);
            logger.debug("map: Splitting resource path '{}' into '{}' and '{}'", resourcePath, mappedPath,
                    fragmentQuery);
        } else {
            fragmentQuery = null;
            mappedPath = resourcePath;
        }

        final RequestContext requestContext = new RequestContext(request, resourcePath);
        ParsedParameters parsed = new ParsedParameters(mappedPath);
        
        // 2. add the requested path itself
        if ( !mappedPath.isEmpty() )
            mappings.add(mappedPath);

        // 3. load mappings from the resource path
        populateMappingsFromMapEntries(mappings, Collections.singletonList(mappedPath), requestContext);
        
        // 4. load aliases
        final Resource nonDecoratedResource = resolver.resolveInternal(parsed.getRawPath(), parsed.getParameters());
        if (nonDecoratedResource != null) {
            List<String> aliases = loadAliasesIfApplicable(nonDecoratedResource);
            // avoid duplicating the originally requested path
            aliases.remove(mappedPath);
            // ensure that the first declared alias will be returned first
            Collections.reverse(aliases);
            
            // 5. load mappings for alias
            mappings.addAll(aliases);
            populateMappingsFromMapEntries(mappings, aliases, requestContext);
        }
        
        // 6. add vanity paths
        List<String> vanityPaths = mapEntries.getVanityPathMappings().getOrDefault(mappedPath, Collections.emptyList());
        // vanity paths are prepended to make sure they get returned last
        mappings.addAll(0, vanityPaths);


        // Apply mappings from Resource Mappers
        PathToUriMappingService.Result mappingResult = pathToUriMappingService.map(request, mappings.get(mappings.size() - 1));
        for (Map.Entry<String, SlingUri> mappingFromChain : mappingResult.getIntermediateMappings().entrySet()) {
            mappings.add(mappingFromChain.getValue().toString());
        }

        // 7. apply context path if needed
        mappings.replaceAll(new ApplyContextPath(request));
       
        // 8. set back the fragment query if needed
        if ( fragmentQuery != null ) {
            mappings.replaceAll(path -> path.concat(fragmentQuery));
        }

        mappings.forEach( path -> {
            logger.debug("map: Returning URL {} as mapping for path {}", path, resourcePath);
        });

        Collections.reverse(mappings);
        
        return new LinkedHashSet<>(mappings);
    }

    private List<String> loadAliasesIfApplicable(final Resource nonDecoratedResource) {
        //Invoke the decorator for the resolved resource
        Resource res = resourceDecorator.decorate(nonDecoratedResource); 

        // keep, what we might have cut off in internal resolution
        final String resolutionPathInfo = res.getResourceMetadata().getResolutionPathInfo();

        logger.debug("map: Path maps to resource {} with path info {}", res, resolutionPathInfo);

        // find aliases for segments. we can't walk the parent chain
        // since the request session might not have permissions to
        // read all parents SLING-2093
        PathGenerator pathBuilder = new PathGenerator();

        // make sure to append resolutionPathInfo, if present
        pathBuilder.setResolutionPathInfo(resolutionPathInfo);
        
        Resource current = res;
        String path = res.getPath();
        while (path != null) {
            List<String> aliases = Collections.emptyList();
            // read alias only if we can read the resources and it's not a jcr:content leaf
            if (current != null && !path.endsWith(ResourceResolverImpl.JCR_CONTENT_LEAF)) {
                aliases = readAliases(path, current);
            }
            // build the path from the name segments or aliases
            pathBuilder.insertSegment(aliases, ResourceUtil.getName(path));
            path = ResourceUtil.getParent(path);
            if ("/".equals(path)) {
                path = null;
            } else if (path != null) {
                current = res.getResourceResolver().resolve(path);
            }
        }
        
        // and then we have the mapped path to work on
        List<String> mappedPaths = pathBuilder.generatePaths();
        logger.debug("map: Alias mapping resolves to paths {}", mappedPaths);
        
        return mappedPaths;
    }
    
    private List<String> readAliases(String path, Resource current) {
        if (optimizedAliasResolutionEnabled) {
            logger.debug("map: Optimize Alias Resolution is Enabled");
            String parentPath = ResourceUtil.getParent(path);
            
            if ( parentPath == null )
                return Collections.emptyList();
            
            final Map<String, String> aliases = mapEntries.getAliasMap(parentPath);
            
            if ( aliases == null || !aliases.containsValue(current.getName()) ) 
                return Collections.emptyList();
            
            return aliases.entrySet().stream()
                .filter( e -> current.getName().contentEquals(e.getValue()) )
                .map( Entry::getKey )
                .collect(Collectors.toList());
            
        } else {
            logger.debug("map: Optimize Alias Resolution is Disabled");
            String[] aliases = ResourceResolverControl.getProperty(current, ResourceResolverImpl.PROP_ALIAS, String[].class);
            if ( aliases == null || aliases.length == 0 )
                return Collections.emptyList();
            if ( aliases.length == 1 )
                return Collections.singletonList(aliases[0]);
            return Arrays.asList(aliases);
        }        
    }

    private void populateMappingsFromMapEntries(List<String> mappings, List<String> mappedPathList,
            final RequestContext requestContext) {
        boolean mappedPathIsUrl = false;
        for ( String mappedPath : mappedPathList ) {
            for (final MapEntry mapEntry : mapEntries.getMapMaps()) {
                final String[] mappedPaths = mapEntry.replace(mappedPath);
                if (mappedPaths != null) {
    
                    logger.debug("map: Match for Entry {}", mapEntry);
    
                    mappedPathIsUrl = !mapEntry.isInternal();
    
                    if (mappedPathIsUrl && requestContext.hasUri() ) {
    
                        mappedPath = null;
    
                        for (final String candidate : mappedPaths) {
                            if (candidate.startsWith(requestContext.getUri())) {
                                mappedPath = candidate.substring(requestContext.getUri().length() - 1);
                                mappedPathIsUrl = false;
                                logger.debug("map: Found host specific mapping {} resolving to {}", candidate, mappedPath);
                                break;
                            } else if (candidate.startsWith(requestContext.getSchemeWithPrefix()) && mappedPath == null) {
                                mappedPath = candidate;
                            }
                        }
    
                        if (mappedPath == null) {
                            mappedPath = mappedPaths[0];
                        }
    
                    } else {
    
                        // we can only go with assumptions selecting the first entry
                        mappedPath = mappedPaths[0];
    
                    }
    
                    logger.debug("map: MapEntry {} matches, mapped path is {}", mapEntry, mappedPath);
                    
                    mappings.add(mappedPath);
    
                    break;
                }
            }
        }
    }
    
    private class RequestContext {
        
        private final String uri;
        private final String schemeWithPrefix;
        
        private RequestContext(HttpServletRequest request, String resourcePath) {
            if ( request != null ) {
                this.uri = MapEntry.getURI(request.getScheme(), request.getServerName(), request.getServerPort(), "/");
                this.schemeWithPrefix = request.getScheme().concat("://");
                logger.debug("map: Mapping path {} for {} (at least with scheme prefix {})",  resourcePath,
                        uri, schemeWithPrefix );
            } else {
                this.uri = null;
                this.schemeWithPrefix = null;
                logger.debug("map: Mapping path {} for default", resourcePath);
            }
            
        }
        
        public String getUri() {
            return uri;
        }
        
        public String getSchemeWithPrefix() {
            return schemeWithPrefix;
        }
        
        public boolean hasUri() {
            return uri != null && schemeWithPrefix != null;
        }
    }
    
    private class ApplyContextPath implements UnaryOperator<String> {
        
        private final HttpServletRequest req;
        
        private ApplyContextPath(HttpServletRequest req) {
            this.req = req;
        }

        @Override
        public String apply(String path) {
            
            String mappedPath = path;
            
            // [scheme:][//authority][path][?query][#fragment]
            try {
                // use commons-httpclient's URI instead of java.net.URI, as it can
                // actually accept *unescaped* URIs, such as the "mappedPath" and
                // return them in proper escaped form, including the path, via
                // toString()
                final URI uri = new URI(path, false);

                // 1. mangle the namespaces in the path
                path = mangleNamespaces(uri.getPath());

                // 2. prepend servlet context path if we have a request
                if (req != null && req.getContextPath() != null && req.getContextPath().length() > 0) {
                    path = req.getContextPath().concat(path);
                }
                // update the path part of the URI
                uri.setPath(path);

                mappedPath = uri.toString();
            } catch (final URIException e) {
                logger.warn("map: Unable to mangle namespaces for " + mappedPath + " returning unmangled", e);
            }

            return mappedPath;
        }

        private String mangleNamespaces(String absPath) {
            if ( absPath != null && namespaceMangler != null && namespaceMangler instanceof JcrNamespaceMangler ) {
                absPath = ((JcrNamespaceMangler) namespaceMangler).mangleNamespaces(resolver, logger, absPath);
            }

            return absPath;
        }
    }
}
