/*
 * 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.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.resourceresolver.impl.ResourceResolverImpl;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * The <code>MapEntry</code> class represents a mapping entry in the mapping
 * configuration tree at <code>/etc/map</code>.
 *
 * @see <a href="https://sling.apache.org/documentation/the-sling-engine/mappings-for-resource-resolution.html">Mappings for Resource Resolution</a>
 */
public class MapEntry implements Comparable<MapEntry> {

    /** default log */
    private final Logger log = LoggerFactory.getLogger(getClass());

    private static final Pattern[] URL_WITH_PORT_MATCH = {
        Pattern.compile("http/([^/]+)(\\.[^\\d/]+)(/.*)?$"),
        Pattern.compile("https/([^/]+)(\\.[^\\d/]+)(/.*)?$") };

    private static final String[] URL_WITH_PORT_REPLACEMENT = {
        "http/$1$2.80$3", "https/$1$2.443$3" };

    private static final Pattern[] PATH_TO_URL_MATCH = {
        Pattern.compile("http/([^/]+)\\.80(/.*)?$"),
        Pattern.compile("https/([^/]+)\\.443(/.*)?$"),
        Pattern.compile("([^/]+)/([^/]+)\\.(\\d+)(/.*)?$"),
        Pattern.compile("([^/]+)/([^/]+)(/.*)?$") };

    private static final String[] PATH_TO_URL_REPLACEMENT = { "http://$1$2",
        "https://$1$2", "$1://$2:$3$4", "$1://$2$3" };

    private final Pattern urlPattern;

    private final String[] redirect;

    private final int status;

    private long order;

    public static String appendSlash(String path) {
        if (!path.endsWith("/")) {
            path = path.concat("/");
        }
        return path;
    }

    /**
     * Returns a string used for matching map entries against the given request
     * or URI parts.
     *
     * @param scheme
     *            The URI scheme
     * @param host
     *            The host name
     * @param port
     *            The port number. If this is negative, the default value used
     *            is 80 unless the scheme is "https" in which case the default
     *            value is 443.
     * @param path
     *            The (absolute) path
     * @return The request path string {scheme}://{host}:{port}{path}.
     */
    public static String getURI(final String scheme, final String host, final int port,
                    final String path) {

        final StringBuilder sb = new StringBuilder();
        sb.append(scheme).append("://").append(host);
        if (port > 0 && !(port == 80 && "http".equals(scheme))
                        && !(port == 443 && "https".equals(scheme))) {
            sb.append(':').append(port);
        }
        sb.append(path);

        return sb.toString();
    }

    public static String fixUriPath(final String uriPath) {
        for (int i = 0; i < URL_WITH_PORT_MATCH.length; i++) {
            final Matcher m = URL_WITH_PORT_MATCH[i].matcher(uriPath);
            if (m.find()) {
            	if (!isRegExp(m.replaceAll("$1$2")))
            	{
                    return m.replaceAll(URL_WITH_PORT_REPLACEMENT[i]);
            	}
            }
        }

        return uriPath;
    }

    /**
     * Converts the resolution path of the form http/host.77/the/path into an
     * URI of the form http://host:77/the/path where any potential default port
     * (80 for http and 443 for https) is actually removed. If the path is just
     * a regular path such as /the/path, this method returns <code>null</code>.
     */
    public static String toURI(final String uriPath) {
        for (int i = 0; i < PATH_TO_URL_MATCH.length; i++) {
            final Matcher m = PATH_TO_URL_MATCH[i].matcher(uriPath);
            if (m.find()) {
                return m.replaceAll(PATH_TO_URL_REPLACEMENT[i]);
            }
        }

        return null;
    }

    public static MapEntry createResolveEntry(String url, final Resource resource,
                    final boolean trailingSlash) {
        final ValueMap props = resource.adaptTo(ValueMap.class);
        if (props != null) {

            // ensure the url contains a port number (if possible)
            url = fixUriPath(url);

            final String redirect = props.get(
                            MapEntries.PROP_REDIRECT_EXTERNAL, String.class);
            if (redirect != null) {
                final int status = props
                                .get(MapEntries.PROP_REDIRECT_EXTERNAL_STATUS,
                                                302);
                return new MapEntry(url, status, trailingSlash, 0, redirect);
            }

            final String[] internalRedirectProps = props.get(ResourceResolverImpl.PROP_REDIRECT_INTERNAL,
                String[].class);
            final String[] internalRedirect = filterRegExp(internalRedirectProps);
            if (internalRedirect != null) {
                return new MapEntry(url, -1, trailingSlash, 0, internalRedirect);
            }
        }

        return null;
    }

    public static List<MapEntry> createMapEntry(String url, final Resource resource,
                    final boolean trailingSlash) {
        final ValueMap props = resource.adaptTo(ValueMap.class);
        if (props != null) {
            final String redirect = props.get(
                            MapEntries.PROP_REDIRECT_EXTERNAL, String.class);
            if (redirect != null) {
                // ignoring external redirects for mapping
                LoggerFactory
                .getLogger(MapEntry.class)
                .info("createMapEntry: Configuration has external redirect to {}; not creating mapping for configuration in {}",
                                redirect, resource.getPath());
                return null;
            }

            // ignore potential regular expression url
            if (isRegExp(url)) {
                LoggerFactory
                .getLogger(MapEntry.class)
                .info("createMapEntry: URL {} contains a regular expression; not creating mapping for configuration in {}",
                                url, resource.getPath());

                return null;
            }

            // check whether the url is a match hooked to then string end
            String endHook = "";
            if (url.endsWith("$")) {
                endHook = "$";
                url = url.substring(0, url.length() - 1);
            }

            // check whether the url is for ANY_SCHEME_HOST
            if (url.startsWith(MapEntries.ANY_SCHEME_HOST)) {
                url = url.substring(MapEntries.ANY_SCHEME_HOST.length());
            }

            final String[] internalRedirect = props
                            .get(ResourceResolverImpl.PROP_REDIRECT_INTERNAL,
                                            String[].class);
            if (internalRedirect != null) {

                // check whether the url is considered external or internal
                int status = -1;
                final String pathUri = toURI(url);
                if (pathUri != null) {
                    url = pathUri;
                    status = 302;
                }

                final List<MapEntry> prepEntries = new ArrayList<MapEntry>(
                                internalRedirect.length);
                for (final String redir : internalRedirect) {
                    if (!redir.contains("$")) {
                    	MapEntry mapEntry = null;
                    	try{
                    		mapEntry = new MapEntry(redir.concat(endHook), status, trailingSlash, 0, url);
                    	}catch (IllegalArgumentException iae){
                    		//ignore this entry
                            LoggerFactory
                            .getLogger(MapEntry.class)
                    		.debug("Ignoring mapping due to exception: " + iae.getMessage(), iae);
                    	}
                    	if (mapEntry!=null){
                    		prepEntries.add(mapEntry);
                    	}
                    }
                }

                if (prepEntries.size() > 0) {
                    return prepEntries;
                }
            }
        }

        return null;
    }

    public MapEntry(String url, final int status, final boolean trailingSlash,
                    final long order, final String... redirect) {

        // ensure trailing slashes on redirects if the url
        // ends with a trailing slash
        if (trailingSlash) {
            url = appendSlash(url);
            for (int i = 0; i < redirect.length; i++) {
                redirect[i] = appendSlash(redirect[i]);
            }
        }

        // ensure pattern is hooked to the start of the string
        if (!url.startsWith("^")) {
            url = "^".concat(url);
        }

        try {
        	this.urlPattern = Pattern.compile(url);
        } catch (Exception e){
        	throw new IllegalArgumentException("Bad url pattern: " + url,e);
        }

        this.redirect = redirect;
        this.status = status;
        this.order = order;
    }

    /**
     * Replaces the specified value according to the rules of this entry
     * 
     * @param value the value to replace
     * @return a replaced value of <code>null</code> if the value does not match
     */
    public @Nullable String[] replace(final @NotNull String value) {
        final Matcher m = urlPattern.matcher(value);
        if (m.find()) {
            final String[] redirects = getRedirect();
            final String[] results = new String[redirects.length];
            for (int i = 0; i < redirects.length; i++) {
            	try {
            		String redirect = redirects[i];
            		// SLING-7881 - if the value is a selector on the root resource then the
            		// result will need to remove the trailing slash from the path
            		if (redirect.length() > 1 && redirect.endsWith("/")) {
            			if (value.length() > m.end()) {
            				if ('.' == value.charAt(m.end())) {
            					//the suffix starts with a dot and the redirect prefix ends with
            					// a slash so we need to remove the trailing slash from the prefix
            					// value to make a valid path when they are combined.
            					// 
            					// for example: http/localhost.8080/.2.json should become /content.2.json
            					//   instead of /content/.2.json
            					redirect = redirect.substring(0, redirect.length() - 1);
            				}
            			}
            		}
            		results[i] = m.replaceFirst(redirect);
            	} catch (final StringIndexOutOfBoundsException siob){
            		log.debug("Exception while replacing, ignoring entry {} ", redirects[i], siob);
                } catch (final IllegalArgumentException iae){
                    log.debug("Exception while replacing, ignoring entry {} ", redirects[i], iae);
             	}
            }
            return results;
        }

        return null;
    }

    public String getPattern() {
        return urlPattern.toString();
    }

    public String[] getRedirect() {
        return redirect;
    }

    public boolean isInternal() {
        return getStatus() < 0;
    }

    public int getStatus() {
        return status;
    }

    // ---------- Comparable

    public int compareTo(final MapEntry m) {
        if (this == m) {
            return 0;
        }

        final String ownPatternString = urlPattern.toString();
        final String mPatternString = m.urlPattern.toString();

        final int tlen = ownPatternString.length();
        final int mlen = mPatternString.length();
        if (tlen < mlen) {
            return 1;
        } else if (tlen > mlen) {
            return -1;
        }

        // lengths are equal, but the entries are not
        // so order based on the pattern
        int stringComparison = ownPatternString.toString().compareTo(mPatternString);
        if (stringComparison == 0 && order != m.order) {
            if (m.order > order) {
                return 1;
            } else {
                return -1;
            }
        }
        return stringComparison;
    }

    // ---------- Object overwrite

    @Override
    public String toString() {
        final StringBuilder buf = new StringBuilder();
        buf.append("MapEntry: match:").append(urlPattern);

        buf.append(", replacement:");
        if (getRedirect().length == 1) {
            buf.append(getRedirect()[0]);
        } else {
            buf.append(Arrays.asList(getRedirect()));
        }

        if (isInternal()) {
            buf.append(", internal");
        } else {
            buf.append(", status:").append(getStatus());
        }
        return buf.toString();
    }

    // ---------- helper

    /**
     * Returns <code>true</code> if the string contains unescaped regular
     * expression special characters '+', '*', '?', '|', '(', '), '[', and ']'
     *
     * @param string
     * @return
     */
    private static boolean isRegExp(final String string) {
        for (int i = 0; i < string.length(); i++) {
            final char c = string.charAt(i);
            if (c == '\\') {
                i++; // just skip
            } else if ("+*?|()[]".indexOf(c) >= 0) {
                return true; // assume an unescaped pattern character
            }
        }
        return false;
    }

    /**
     * Returns an array of strings copied from the given strings where any
     * regular expressions in the array are removed. If the input is
     * <code>null</code> or no strings are provided <code>null</code> is
     * returned. <code>null</code> is also returned if the strings only contain
     * regular expressions.
     */
    private static String[] filterRegExp(final String... strings) {
        if (strings == null || strings.length == 0) {
            return null;
        }

        ArrayList<String> list = new ArrayList<String>(strings.length);
        for (String string : strings) {
            if (!isRegExp(string)) {
                list.add(string);
            }
        }

        return list.isEmpty() ? null : (String[]) list.toArray(new String[list.size()]);
    }

    void setOrder(long order) {
        this.order = order;
    }
}
