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

import org.apache.commons.httpclient.URIException;
import org.apache.commons.httpclient.util.URIUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.HashMap;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * A partial implementation of URI Template expansion
 * as specified by the <a href="http://bitworking.org/projects/URI-Templates/spec/draft-gregorio-uritemplate-03.html">URI template specification</a>.
 * <p/><strong>Limitations</strong>
 * <br/>The only operation implemented so far is <a href="http://bitworking.org/projects/URI-Templates/spec/draft-gregorio-uritemplate-03.html#var">Var substitution</a>. If an expansion template for another operation (join, neg, opt, etc) is found,
 * an {@link UnsupportedOperationException} is thrown.
 * <p/>
 * <p/>
 * <p/><strong>Escaping Considerations</strong>
 * <br/>Replacement and default values are escaped. All characters except unreserved (as defined by <a href="http://tools.ietf.org/html/rfc2396#appendix-A">rfc2396</a>) are escaped.
 * <br/> unreserved    = alphanum | mark
 * <br/> mark          = "-" | "_" | "." | "!" | "~" | "*" | "'" |  "(" | ")"
 * <p/>
 * <a href="http://tools.ietf.org/html/rfc2396">Rfc2396</a> is used to be compliant with {@linkplain java.net.URI java.net.URI}.
 * <p/>
 * <p/><strong>Examples:</strong>
 * <br/>
 * Given the following template variable names and values:
 * <ul>
 * <li>foo = tag</li>
 * <li>bar = java</li>
 * <li>name = null</li>
 * <li>date = 2008/05/09</li>
 * </ul>
 * <p/>The following URI Templates will be expanded as shown:
 * <br/>http://example.com/{foo}/{bar}.{format=xml}
 * <br/>http://example.com/tag/java.xml
 * <br/>
 * <br/>http://example.com/tag/java.{format}
 * <br/>http://example.com/tag/java.
 * <br/>
 * <br/>http://example.com/{foo}/{name}
 * <br/>http://example.com/tag/
 * <br/>
 * <br/>http://example.com/{foo}/{name=james}
 * <br/>http://example.com/tag/james
 * <br/>
 * <br/>http://example.org/{date}
 * <br/>http://example.org/2008%2F05%2F09
 * <br/>
 * <br/>http://example.org/{-join|&|foo,bar,xyzzy,baz}/{date}
 * <br/>--> UnsupportedOperationException
 *
 * @author <a href="mailto:midon@intalio.com">Alexis Midon</a>
 * @see #varSubstitution(String, Object[], java.util.Map)
 */

public class URITemplate {

    private static final Logger log = LoggerFactory.getLogger(URITemplate.class);


    public static final String EXPANSION_REGEX = "\\{[^\\}]+\\}";
    // compiled pattern of the regex
    private static final Pattern PATTERN = Pattern.compile(EXPANSION_REGEX);

    /**
     * Implements the function describes in <a href="http://bitworking.org/projects/URI-Templates/spec/draft-gregorio-uritemplate-03.html#appendix_a">the spec</a>
     *
     * @param expansion, an expansion template (with the surrounding braces)
     * @return an array of object containing the operation name, the operation argument, a map of <var, default value (null if none)>
     */
    public static Object[] parseExpansion(String expansion) {
        // remove surrounding braces if any
        if (expansion.matches(EXPANSION_REGEX)) {
            expansion = expansion.substring(1, expansion.length() - 1);
        }
        String[] r;
        if (expansion.contains("|")) {
            // (op, arg, vars)
            r = expansion.split("\\|", -1);
            // remove the leading '-' of the operation
            r[0] = r[0].substring(1);
        } else {
            r = new String[]{null, null, expansion};
        }

        // parse the vars
        Map vars = new HashMap();
        String[] var = r[2].split(",");
        for (String s : var) {
            if (s.contains("=")) {
                String[] a = s.split("=");
                vars.put(a[0], a[1]);
            } else {
                vars.put(s, null);
            }
        }
        // op, arg, vars
        return new Object[]{r[0], r[1], vars};
    }

    /**
     * Simply build a map from nameValuePairs and pass it to {@link #expand(String, java.util.Map)}
     *
     * @param nameValuePairs an array containing of name, value, name, value, and so on.  Null values are allowed.
     * @see # expand (String, java.util.Map)
     */
    public static String expand(String uriTemplate, String... nameValuePairs) throws URIException, UnsupportedOperationException {
        return expand(uriTemplate, toMap(nameValuePairs));
    }

    /**
     * A partial implementation of URI Template expansion
     * as specified by the <a href="http://bitworking.org/projects/URI-Templates/spec/draft-gregorio-uritemplate-03.html">URI template specification</a>.
     * <p/>
     * The only operation implemented as of today is "Var Substitution". If an expansion template for another operation (join, neg, opt, etc) is found,
     * an {@link UnsupportedOperationException} will be thrown.
     * <p/>
     * See {@link #varSubstitution(String, Object[], java.util.Map)}
     *
     * @param uriTemplate    the URI template
     * @param nameValuePairs a Map of &lt;name, value&gt;. Null values are allowed.
     * @return a copy of uri template in which substitutions have been made (if possible)
     * @throws URIException                  if the default protocol charset is not supported
     * @throws UnsupportedOperationException if the operation is not supported. Currently only var substitution is supported.
     * @see #varSubstitution(String, Object[], java.util.Map)
     */
    public static String expand(String uriTemplate, Map<String, String> nameValuePairs) throws URIException, UnsupportedOperationException {
        return expand(uriTemplate, nameValuePairs, false);
    }

    /**
     * Same as {@link #expand(String, java.util.Map)} but preserve an expansion template if the corresponding variable
     * is not defined in the {@code nameValuePairs} map (i.e. map.contains(var)==false).
     * <br/>Meaning that a template may be returned.
     * <br/> If a default value exists for the undefined value, it will be used to replace the expansion pattern.
     * <p/>
     * <strong>Beware that this behavior deviates from the URI Template specification.</strong>
     * <p/>
     * For instance:
     * <br/>Given the following template variable names and values:
     * <ul>
     * <li>bar = java</li>
     * <li>foo undefined
     * </ul>
     * <p/>The following expansion templates will be expanded as shown if {@code preserveUndefinedVar} is true:
     * <br/>http://example.com/{bar}
     * <br/>http://example.com/java
     * <br/>
     * <br/>{foo=a_default_value}
     * <br/>a_default_value
     * <br/>
     * <br/>http://example.com/{bar}/{foo}
     * <br/>http://example.com/java/{foo}
     *
     * @see #expand(String, java.util.Map)
     */
    public static String expandLazily(String uriTemplate, Map<String, String> nameValuePairs) throws URIException, UnsupportedOperationException {
        return expand(uriTemplate, nameValuePairs, true);
    }

    /**
     * @see #expandLazily(String, java.util.Map)
     */
    public static String expandLazily(String uriTemplate, String... nameValuePairs) throws URIException {
        return expandLazily(uriTemplate, toMap(nameValuePairs));
    }


    /**
     * @see #varSubstitution(String, Object[], java.util.Map, boolean)
     * @see #expandLazily(String, String[])
     */
    private static String expand(String uriTemplate, Map<String, String> nameValuePairs, boolean preserveUndefinedVar) throws URIException, UnsupportedOperationException {
        Matcher m = PATTERN.matcher(uriTemplate);
        // Strings are immutable in java
        // so let's use a buffer, and append all substrings between 2 matches and the replacement value for each match
        StringBuilder sb = new StringBuilder(uriTemplate.length());
        int prevEnd = 0;
        while (m.find()) {
            // append the string between two matches
            sb.append(uriTemplate.substring(prevEnd, m.start()));
            prevEnd = m.end();

            // expansion pattern with braces
            String expansionPattern = uriTemplate.substring(m.start(), m.end());
            Object[] expansionInfo = parseExpansion(expansionPattern);
            String operationName = (String) expansionInfo[0];
            // here we have to know which operation apply
            if (operationName != null) {
                final String msg = "Operation not supported [" + operationName + "]. This expansion pattern [" + expansionPattern + "] is not valid.";
                if (log.isWarnEnabled()) log.warn(msg);
                throw new UnsupportedOperationException(msg);
            } else {
                // here we care only for var substitution, i.e expansion patterns with no operation name
                sb.append(varSubstitution(expansionPattern, expansionInfo, nameValuePairs, preserveUndefinedVar));
            }

        }
        if (sb.length() == 0) {
            // return the template itself if no match (String are immutable in java, no need to clone the template)
            return uriTemplate;
        } else {
            // don't forget the remaining part
            sb.append(uriTemplate.substring(prevEnd, uriTemplate.length()));
            return sb.toString();
        }
    }

    /**
     * An implementation of var substitution as defined by the
     * <a href="http://bitworking.org/projects/URI-Templates/spec/draft-gregorio-uritemplate-03.html#var">URI template specification</a>.
     * <p/>
     * If for a given variable, the variable is in the name/value map but the associated value is null. The variable will be replaced with an empty string or with the default value if any.
     *
     * @param expansionPattern an expansion pattern (not a uri template) e.g. "{foo}"
     * @param expansionInfo    the result of {@link #parseExpansion(String)} for the given expansion pattern
     * @param nameValuePairs   the Map<String, String> of names and associated values. May containt null values.
     * @return the expanded string, properly escaped.
     * @throws URIException if an encoding exception occured
     * @see org.apache.commons.httpclient.util.URIUtil#encodeWithinQuery(String)
     * @see java.net.URI
     */
    public static String varSubstitution(String expansionPattern, Object[] expansionInfo, Map<String, String> nameValuePairs) throws URIException {
        return varSubstitution(expansionPattern, expansionInfo, nameValuePairs, false);
    }

    /**
     * Same as {@link #varSubstitution(String, Object[], java.util.Map)} but the {@code preserveUndefinedVar} boolean
     * argument (if {@code true}) allows to preserve an expansion template if the corresponding variable is not defined in the {@code nameValuePairs} map (i.e. map.contains(var)==false).
     * <br/> If a default value exists for the undefined value, it will be used to replace the expansion pattern.
     * <p/>
     * <strong>Beware that this behavior deviates from the URI Template specification.</strong>
     * <p/>
     * For instance:
     * <br/>Given the following template variable names and values:
     * <ul>
     * <li>bar = java</li>
     * <li>foo undefined
     * </ul>
     * <p/>The following expansion templates will be expanded as shown if {@code preserveUndefinedVar} is true:
     * <br/>{bar}
     * <br/>java
     * <br/>
     * <br/>{foo=a_default_value}
     * <br/>a_default_value
     * <br/>
     * <br/>{foo}
     * <br/>{foo}
     */
    public static String varSubstitution(String expansionPattern, Object[] expansionInfo, Map<String, String> nameValuePairs, boolean preserveUndefinedVar) throws URIException {
        Map vars = (Map) expansionInfo[2];
        // only one var per pattern
        Map.Entry e = (Map.Entry) vars.entrySet().iterator().next();
        String var = (String) e.getKey();
        String defaultValue = (String) e.getValue();
        boolean hasDefaultValue = defaultValue != null;
        // this boolean indicates if the var is mentioned in the map, not that the associated value is not null.
        boolean varDefined = nameValuePairs.containsKey(var);
        String providedValue = nameValuePairs.get(var);
        String res;
        boolean escapingNeeded = true;
        if (varDefined) {
            if (providedValue == null && !hasDefaultValue) {
                res = "";
            } else {
                res = providedValue != null ? providedValue : defaultValue;
            }
        } else {
            // If the variable is undefined and no default value is given then substitute with the empty string,
            // except if preserveUndefinedVar is true

            if (hasDefaultValue) {
                res = defaultValue;
            } else {
                if (preserveUndefinedVar) {
                    res = expansionPattern;
                    escapingNeeded = false;
                } else {
                    res = "";
                }
            }
        }
        // We assume that the replacement value is for the query part of the URI.
        // Actually the query allows less character than the path part. $%&+,:@
        // (acording to RFC2396
        return escapingNeeded ? URIUtil.encodeWithinQuery(res) : res;
    }


    private static Map<String, String> toMap(String... nameValuePairs) {
        if (nameValuePairs.length % 2 != 0) {
            throw new IllegalArgumentException("An even number of elements is expected.");
        }
        Map<String, String> m = new HashMap<String, String>();
        for (int i = 0; i < nameValuePairs.length; i = i + 2) {
            m.put(nameValuePairs[i], nameValuePairs[i + 1]);
        }
        return m;
    }
}
