/*
 * $Id$
 *
 * 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.tiles.definition.pattern;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.tiles.Attribute;
import org.apache.tiles.Definition;
import org.apache.tiles.Expression;
import org.apache.tiles.ListAttribute;

/**
 * Utilities for pattern matching and substitution.
 *
 * @version $Rev$ $Date$
 * @since 2.2.0
 */
public final class PatternUtil {

    /**
     * The root locale. Notice that this is a replacement for Locale.ROOT for
     * Java 1.6.
     */
    private static final Locale ROOT_LOCALE = new Locale("", "");

    /** Pattern to find {.*} occurrences that do not match {[0-9]+} so to prevent MessageFormat from crashing.
     */
    private static final Pattern INVALID_FORMAT_ELEMENT = Pattern.compile("\\Q{\\E[\\D^}]+\\Q}\\E");

    /**
     * Private constructor to avoid instantiation.
     */
    private PatternUtil() {
    }

    /**
     * Creates a definition given its representation with wildcards and
     * attribute values with placeholders, replacing real values into
     * placeholders.
     *
     * @param d The definition to replace.
     * @param name The name of the definition to be created.
     * @param vars The variables to be substituted.
     * @return The definition that can be rendered.
     * @since 2.2.0
     */
    public static Definition replacePlaceholders(Definition d, String name,
            Object... vars) {
        Definition nudef = new Definition();

        nudef.setExtends(replace(d.getExtends(), vars));
        nudef.setName(name);
        nudef.setPreparer(replace(d.getPreparer(), vars));
        Attribute templateAttribute = d.getTemplateAttribute();
        if (templateAttribute != null) {
            nudef.setTemplateAttribute(replaceVarsInAttribute(
                    templateAttribute, vars));
        }

        Set<String> attributeNames = d.getLocalAttributeNames();
        if (attributeNames != null && !attributeNames.isEmpty()) {
            for (String attributeName : attributeNames) {
                Attribute attr = d.getLocalAttribute(attributeName);
                Attribute nuattr = replaceVarsInAttribute(attr, vars);

                nudef.putAttribute(replace(attributeName, vars), nuattr);
            }
        }

        attributeNames = d.getCascadedAttributeNames();
        if (attributeNames != null && !attributeNames.isEmpty()) {
            for (String attributeName : attributeNames) {
                Attribute attr = d.getCascadedAttribute(attributeName);
                Attribute nuattr = replaceVarsInAttribute(attr, vars);

                nudef.putAttribute(replace(attributeName, vars), nuattr, true);
            }
        }

        return nudef;
    }

    /**
     * Creates a new map that contains all the entries of the
     * <code>defsMap</code> whose keys are contained in <code>keys</code>.
     *
     * @param map The map to read.
     * @param keys The keys to extract.
     * @param <K> The key of the map.
     * @param <V> The value of the map.
     * @return The extracted map.
     * @since 2.2.1
     */
    public static <K, V> Map<K, V> createExtractedMap(Map<K, V> map, Set<K> keys) {
        Map<K, V> retValue = new LinkedHashMap<K, V>();
        for (K key : keys) {
            retValue.put(key, map.get(key));
        }
        return retValue;
    }

    /**
     * Replaces variables into an attribute.
     *
     * @param attr The attribute to be used as a basis, containing placeholders
     * for variables.
     * @param vars The variables to replace.
     * @return A new instance of an attribute, whose properties have been
     * replaced with variables' values.
     */
    private static Attribute replaceVarsInAttribute(Attribute attr,
            Object... vars) {
        Attribute nuattr;
        if (attr instanceof ListAttribute) {
            nuattr = replaceVarsInListAttribute((ListAttribute) attr, vars);
        } else {
            nuattr = replaceVarsInSimpleAttribute(attr, vars);
        }
        return nuattr;
    }

    /**
     * Replaces variables into a simple (not list) attribute.
     *
     * @param attr The attribute to be used as a basis, containing placeholders
     * for variables.
     * @param vars The variables to replace.
     * @return A new instance of an attribute, whose properties have been
     * replaced with variables' values.
     */
    private static Attribute replaceVarsInSimpleAttribute(Attribute attr,
            Object... vars) {
        Attribute nuattr;
        nuattr = new Attribute();

        nuattr.setRole(replace(attr.getRole(), vars));
        nuattr.setRenderer(attr.getRenderer());
        Expression expressionObject = attr.getExpressionObject();
        if (expressionObject != null) {
            Expression newExpressionObject = Expression
                    .createExpression(replace(expressionObject.getExpression(), vars), expressionObject.getLanguage());
            nuattr.setExpressionObject(newExpressionObject);
        }

        Object value = attr.getValue();
        if (value instanceof String) {
            value = replace((String) value, vars);
        }
        nuattr.setValue(value);
        return nuattr;
    }

    /**
     * Replaces variables into a list attribute.
     *
     * @param listAttr The attribute to be used as a basis, containing attributes
     * that may contain placeholders for variables.
     * @param vars The variables to replace.
     * @return A new instance of an attribute, whose properties have been
     * replaced with variables' values.
     */
    private static Attribute replaceVarsInListAttribute(ListAttribute listAttr,
            Object... vars) {
        Attribute nuattr;
        ListAttribute nuListAttr = new ListAttribute();
        nuListAttr.setInherit(listAttr.isInherit());
        List<Attribute> nuItems = nuListAttr.getValue();
        for (Object item : listAttr.getValue()) {
            Attribute child = (Attribute) item;
            child = replaceVarsInAttribute(child, vars);
            nuItems.add(child);
        }
        nuattr = nuListAttr;
        return nuattr;
    }

    /**
     * Replaces a string with placeholders using values of a variable map.
     *
     * @param st The string to replace.
     * @param vars The variables.
     * @return The replaced string.
     */
    private static String replace(String st, Object... vars) {
        if (st != null && st.indexOf('{') >= 0) {

            // replace them with markers
            List<String> originals = new ArrayList<String>();
            for(Matcher m = INVALID_FORMAT_ELEMENT.matcher(st); m.find() ; m = INVALID_FORMAT_ELEMENT.matcher(st)) {
                originals.add(m.group());
                st = m.replaceFirst("INVALID_FORMAT_ELEMENT");
            }

            // do the MessageFormat replacement (escaping quote characters)
            st = new MessageFormat(st.replaceAll("'", "'''"), ROOT_LOCALE)
                    .format(vars, new StringBuffer(), null).toString();

            // return the markers to their original invalid occurrences
            for (String original : originals) {
                st = st.replaceFirst("INVALID_FORMAT_ELEMENT", original);
            }
        }
        return st;
    }
}
