/*
 *  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.tools.ant.types;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;
import java.util.Stack;
import java.util.TreeMap;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.resources.MappedResource;
import org.apache.tools.ant.types.resources.PropertyResource;
import org.apache.tools.ant.util.FileNameMapper;
import org.apache.tools.ant.util.regexp.RegexpMatcher;
import org.apache.tools.ant.util.regexp.RegexpMatcherFactory;

/**
 * A set of properties.
 *
 * @since Ant 1.6
 */
public class PropertySet extends DataType implements ResourceCollection {

    private boolean dynamic = true;
    private boolean negate = false;
    private Set<String> cachedNames;
    private List<PropertyRef> ptyRefs = new ArrayList<PropertyRef>();
    private List<PropertySet> setRefs = new ArrayList<PropertySet>();
    private Mapper mapper;

    /**
     * This is a nested class containing a reference to some properties
     * and optionally a source of properties.
     */
    public static class PropertyRef {

        private int count;
        private String name;
        private String regex;
        private String prefix;
        private String builtin;

        /**
         * Set the name.
         * @param name a <code>String</code> value.
         */
        public void setName(String name) {
            assertValid("name", name);
            this.name = name;
        }

        /**
         * Set the regular expression to use to filter the properties.
         * @param regex a regular expression.
         */
        public void setRegex(String regex) {
            assertValid("regex", regex);
            this.regex = regex;
        }

        /**
         * Set the prefix to use.
         * @param prefix a <code>String</code> value.
         */
        public void setPrefix(String prefix) {
            assertValid("prefix", prefix);
            this.prefix = prefix;
        }

        /**
         * Builtin property names - all, system or commandline.
         * @param b an enumerated <code>BuildinPropertySetName</code> value.
         */
        public void setBuiltin(BuiltinPropertySetName b) {
            String pBuiltIn = b.getValue();
            assertValid("builtin", pBuiltIn);
            this.builtin = pBuiltIn;
        }

        private void assertValid(String attr, String value) {
            if (value == null || value.length() < 1) {
                throw new BuildException("Invalid attribute: " + attr);
            }

            if (++count != 1) {
                throw new BuildException("Attributes name, regex, and "
                    + "prefix are mutually exclusive");
            }
        }

        /**
         * A debug toString().
         * @return a string version of this object.
         */
        public String toString() {
            return "name=" + name + ", regex=" + regex + ", prefix=" + prefix
                + ", builtin=" + builtin;
        }

    } //end nested class

    /**
     * Allow properties of a particular name in the set.
     * @param name the property name to allow.
     */
    public void appendName(String name) {
        PropertyRef r = new PropertyRef();
        r.setName(name);
        addPropertyref(r);
    }

    /**
     * Allow properties whose names match a regex in the set.
     * @param regex the regular expression to use.
     */
    public void appendRegex(String regex) {
        PropertyRef r = new PropertyRef();
        r.setRegex(regex);
        addPropertyref(r);
    }

    /**
     * Allow properties whose names start with a prefix in the set.
     * @param prefix the prefix to use.
     */
    public void appendPrefix(String prefix) {
        PropertyRef r = new PropertyRef();
        r.setPrefix(prefix);
        addPropertyref(r);
    }

    /**
     * Allow builtin (all, system or commandline) properties in the set.
     * @param b the type of builtin properties.
     */
    public void appendBuiltin(BuiltinPropertySetName b) {
        PropertyRef r = new PropertyRef();
        r.setBuiltin(b);
        addPropertyref(r);
    }

    /**
     * Set a mapper to change property names.
     * @param type mapper type.
     * @param from source pattern.
     * @param to output pattern.
     */
    public void setMapper(String type, String from, String to) {
        Mapper m = createMapper();
        Mapper.MapperType mapperType = new Mapper.MapperType();
        mapperType.setValue(type);
        m.setType(mapperType);
        m.setFrom(from);
        m.setTo(to);
    }

    /**
     * Add a property reference (nested element) to the references to be used.
     * @param ref a property reference.
     */
    public void addPropertyref(PropertyRef ref) {
        assertNotReference();
        setChecked(false);
        ptyRefs.add(ref);
    }

    /**
     * Add another property set to this set.
     * @param ref another property set.
     */
    public void addPropertyset(PropertySet ref) {
        assertNotReference();
        setChecked(false);
        setRefs.add(ref);
    }

    /**
     * Create a mapper to map the property names.
     * @return a mapper to be configured.
     */
    public Mapper createMapper() {
        assertNotReference();
        if (mapper != null) {
            throw new BuildException("Too many <mapper>s!");
        }
        mapper = new Mapper(getProject());
        setChecked(false);
        return mapper;
    }

    /**
     * Add a nested FileNameMapper.
     * @param fileNameMapper the mapper to add.
     * @since Ant 1.6.3
     */
    public void add(FileNameMapper fileNameMapper) {
        createMapper().add(fileNameMapper);
    }

    /**
     * Set whether to reevaluate the set every time the set is used.
     * Default is true.
     *
     * @param dynamic if true, reevaluate the property set each time
     *                the set is used. if false cache the property set
     *                the first time and use the cached set on subsequent
     *                occasions.
     */
    public void setDynamic(boolean dynamic) {
        assertNotReference();
        this.dynamic = dynamic;
    }

    /**
     * Set whether to negate results.
     * If "true", all properties not selected by nested elements will be returned.
     *  Default is "false".
     * @param negate if true, negate the selection criteria.
     */
    public void setNegate(boolean negate) {
        assertNotReference();
        this.negate = negate;
    }

    /**
     * Get the dynamic attribute.
     * @return true if the property set is to be evaluated each time it is used.
     */
    public boolean getDynamic() {
        if (isReference()) {
            return getRef().dynamic;
        }
        dieOnCircularReference();
        return dynamic;
    }

    /**
     * Get the mapper attribute.
     * @return the mapper attribute.
     */
    public Mapper getMapper() {
        if (isReference()) {
            return getRef().mapper;
        }
        dieOnCircularReference();
        return mapper;
    }

    /**
     * Convert the system properties to a hashtable.
     * Use propertynames to get the list of properties (including
     * default ones).
     */
    private Hashtable<String, Object> getAllSystemProperties() {
        Hashtable<String, Object>  ret = new Hashtable<String, Object>();
        for (Enumeration<?> e = System.getProperties().propertyNames();
             e.hasMoreElements();) {
            String name = (String) e.nextElement();
            ret.put(name, System.getProperties().getProperty(name));
        }
        return ret;
    }

    /**
     * This is the operation to get the existing or recalculated properties.
     * @return the properties for this propertyset.
     */
    public Properties getProperties() {
        final Properties result = new Properties();
        result.putAll(getPropertyMap());
        return result;
    }

    /**
     *
     * @return Map
     * @since 1.9.0
     */
    private Map<String, Object> getPropertyMap() {
        if (isReference()) {
            return getRef().getPropertyMap();
        }
        dieOnCircularReference();
        final Mapper myMapper = getMapper();
        final FileNameMapper m = myMapper == null ? null : myMapper.getImplementation();

        final Map<String, Object> effectiveProperties = getEffectiveProperties();
        final Set<String> propertyNames = getPropertyNames(effectiveProperties);
        final Map<String, Object> result = new HashMap<String, Object>();

        //iterate through the names, get the matching values
        for (String name : propertyNames) {
            Object value = effectiveProperties.get(name);
            // TODO should we include null properties?
            // TODO should we query the PropertyHelper for property value to grab potentially shadowed values?
            if (value != null) {
                // may be null if a system property has been added
                // after the project instance has been initialized
                if (m != null) {
                    //map the names
                    String[] newname = m.mapFileName(name);
                    if (newname != null) {
                        name = newname[0];
                    }
                }
                result.put(name, value);
            }
        }
        return result;

    }

    private Map<String, Object> getEffectiveProperties() {
        final Project prj = getProject();
        final Map<String, Object> result = prj == null ? getAllSystemProperties() : prj.getProperties();
        //quick & dirty, to make nested mapped p-sets work:
        for (PropertySet set : setRefs) {
            result.putAll(set.getPropertyMap());
        }
        return result;
    }

    private Set<String> getPropertyNames(Map<String, Object> props) {
        Set<String> names;
        if (getDynamic() || cachedNames == null) {
            names = new HashSet<String>();
            addPropertyNames(names, props);
            // Add this PropertySet's nested PropertySets' property names.
            for (PropertySet set : setRefs) {
                names.addAll(set.getPropertyMap().keySet());
            }
            if (negate) {
                //make a copy...
                HashSet<String> complement = new HashSet<String>(props.keySet());
                complement.removeAll(names);
                names = complement;
            }
            if (!getDynamic()) {
                cachedNames = names;
            }
        } else {
            names = cachedNames;
        }
        return names;
    }

    /**
     * @param  names the output Set to fill with the property names
     *         matching this PropertySet selection criteria.
     * @param  props the current Project properties, passed in to
     *         avoid needless duplication of the Hashtable during recursion.
     */
    private void addPropertyNames(Set<String> names, Map<String, Object> props) {
        if (isReference()) {
            getRef().addPropertyNames(names, props);
        }
        dieOnCircularReference();
        // Add this PropertySet's property names.
        for (PropertyRef r : ptyRefs) {
            if (r.name != null) {
                if (props.get(r.name) != null) {
                    names.add(r.name);
                }
            } else if (r.prefix != null) {
                for (String name : props.keySet()) {
                    if (name.startsWith(r.prefix)) {
                        names.add(name);
                    }
                }
            } else if (r.regex != null) {
                RegexpMatcherFactory matchMaker = new RegexpMatcherFactory();
                RegexpMatcher matcher = matchMaker.newRegexpMatcher();
                matcher.setPattern(r.regex);
                for (String name : props.keySet()) {
                    if (matcher.matches(name)) {
                        names.add(name);
                    }
                }
            } else if (r.builtin != null) {

                if (r.builtin.equals(BuiltinPropertySetName.ALL)) {
                    names.addAll(props.keySet());
                } else if (r.builtin.equals(BuiltinPropertySetName.SYSTEM)) {
                    names.addAll(getAllSystemProperties().keySet());
                } else if (r.builtin.equals(BuiltinPropertySetName
                                              .COMMANDLINE)) {
                    names.addAll(getProject().getUserProperties().keySet());
                } else {
                    throw new BuildException("Impossible: Invalid builtin "
                                             + "attribute!");
                }
            } else {
                throw new BuildException("Impossible: Invalid PropertyRef!");
            }
        }
    }

    /**
     * Performs the check for circular references and returns the
     * referenced PropertySet.
     * @return the referenced PropertySet.
     */
    protected PropertySet getRef() {
        return (PropertySet) getCheckedRef(PropertySet.class, "propertyset");
    }

    /**
     * Sets the value of the refid attribute.
     *
     * @param  r the reference this datatype should point to.
     * @throws BuildException if another attribute was set, since
     *         refid and all other attributes are mutually exclusive.
     */
    public final void setRefid(Reference r) {
        if (!noAttributeSet) {
            throw tooManyAttributes();
        }
        super.setRefid(r);
    }

    /**
     * Ensures this data type is not a reference.
     *
     * <p>Calling this method as the first line of every bean method of
     * this data type (setXyz, addXyz, createXyz) ensure proper handling
     * of the refid attribute.</p>
     *
     * @throws BuildException if the refid attribute was already set, since
     *         refid and all other attributes are mutually exclusive.
     */
    protected final void assertNotReference() {
        if (isReference()) {
            throw tooManyAttributes();
        }
        noAttributeSet = false;
    }

    /**
     * Flag which tracks whether any attribute has been set; used by
     * {@link #assertNotReference()} and {@link #setRefid(Reference)}.
     */
    private boolean noAttributeSet = true;

    /**
     * Used for propertyref's builtin attribute.
     */
    public static class BuiltinPropertySetName extends EnumeratedAttribute {
        static final String ALL = "all";
        static final String SYSTEM = "system";
        static final String COMMANDLINE = "commandline";
        /** {@inheritDoc}. */
        public String[] getValues() {
            return new String[] {ALL, SYSTEM, COMMANDLINE};
        }
    }

    /**
     * A debug toString.
     * This gets a comma separated list of key=value pairs for
     * the properties in the set.
     * The output order is sorted according to the keys' <i>natural order</i>.
     * @return a string rep of this object.
     */
    public String toString() {
        if (isReference()) {
            return getRef().toString();
        }
        dieOnCircularReference();
        StringBuilder b = new StringBuilder();
        TreeMap<String, Object> sorted = new TreeMap<String, Object>(getPropertyMap());
        for (Entry<String, Object> e : sorted.entrySet()) {
            if (b.length() != 0) {
                b.append(", ");
            }
            b.append(e.getKey());
            b.append("=");
            b.append(e.getValue());
        }
        return b.toString();
    }

    /**
     * Fulfill the ResourceCollection interface.
     * @return an Iterator of Resources.
     * @since Ant 1.7
     */
    public Iterator<Resource> iterator() {
        if (isReference()) {
            return getRef().iterator();
        }
        dieOnCircularReference();
        final Set<String> names = getPropertyNames(getEffectiveProperties());

        Mapper myMapper = getMapper();
        final FileNameMapper m = myMapper == null ? null : myMapper.getImplementation();
        final Iterator<String> iter = names.iterator();

        return new Iterator<Resource>() {
            public boolean hasNext() {
                return iter.hasNext();
            }
            public Resource next() {
                PropertyResource p = new PropertyResource(getProject(), iter.next());
                return m == null ? (Resource) p : new MappedResource(p, m);
            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
        };
    }

    /**
     * Fulfill the ResourceCollection contract.
     * @return the size of this ResourceCollection.
     */
    public int size() {
        return isReference() ? getRef().size() : getProperties().size();
    }

    /**
     * Fulfill the ResourceCollection contract.
     * @return whether this is a filesystem-only resource collection.
     */
    public boolean isFilesystemOnly() {
        if (isReference()) {
            return getRef().isFilesystemOnly();
        }
        dieOnCircularReference();
        return false;
    }

    protected synchronized void dieOnCircularReference(Stack<Object> stk, Project p)
        throws BuildException {
        if (isChecked()) {
            return;
        }
        if (isReference()) {
            super.dieOnCircularReference(stk, p);
        } else {
            if (mapper != null) {
                pushAndInvokeCircularReferenceCheck(mapper, stk, p);
            }
            for (PropertySet propertySet : setRefs) {
                pushAndInvokeCircularReferenceCheck(propertySet, stk,
                                                    p);
            }
            setChecked(true);
        }
    }

}
