/*
 *
 *  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.royale.formatter.config;

import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.internal.config.IConfigurationFilter;
import org.apache.royale.compiler.internal.config.annotations.ArgumentNameGenerator;
import org.apache.royale.compiler.internal.config.annotations.Arguments;
import org.apache.royale.compiler.internal.config.annotations.Config;
import org.apache.royale.compiler.internal.config.annotations.RoyaleOnly;
import org.apache.royale.compiler.internal.config.annotations.InfiniteArguments;
import org.apache.royale.compiler.internal.config.annotations.Mapping;
import org.apache.royale.compiler.internal.config.annotations.SoftPrerequisites;
import org.apache.royale.compiler.problems.ConfigurationProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.utils.Trace;
import com.google.common.base.Joiner;
import com.google.common.collect.ImmutableList;

/**
 * The basic idea here is to let you keep all your configuration knowledge in
 * your configuration object, and to automate as much as possible. Reflection is
 * used to convert public fields and setters on your configuration object into
 * settable vars. There are a few key concepts:
 * <p>
 * - You should be able to configure absolutely any object.<br>
 * - Child configuration variables in your config become a dotted hierarchy of
 * varnames<br>
 * - All sources of configuration data are buffered and merged (as string
 * var/vals) before committing to the final configuration. This class acts as
 * the buffer.<br>
 * - Hyphenated variables (i.e. "some-var") are automatically configured by
 * calling your matching setter (i.e. setSomeVar)<br>
 * - Implementing an getSomeVarInfo() method on your class lets you set up more
 * complicated config objects<br>
 * - You can make variables depend on other variables having been set first.
 * This lets you set a root directory in one var and then use its value in
 * another.<br>
 * - Per-variable validation can be performed in setters. Overall validation
 * should take place as a post-process step.<br>
 * - You can keep ConfigurationBuffers around and merge multiple buffers
 * together before committing. Most recent definitions always win.<br>
 * <p>
 * The contract with your configuration class:
 * <p>
 * - You must provide a method with the signature
 * "void setYourVar(ConfigurationValue val)" to set your config var. Your setter
 * method should accept either a single arg of type List or String[], or else an
 * arglist of simple types. For example
 * "void myvar(int a, boolean b, String c")".<br>
 * - You can implement a function with the signature "int yourvar_argcount()" to
 * require a different number of arguments. This limit will be enforced by
 * configurators (command line, file, etc.)<br>
 * - If you provide a setter and explicit parameters (i.e. not List or String[])
 * the number of arguments will be automatically determined.<br>
 * - Each argument to your configuration variable is assumed to have a
 * (potentially non-unique) name. The default is the simple type of the argument
 * (boolean, int, string). If the var takes an undetermined number of args via
 * List or String[], the argname defaults to string.<br>
 * - You can implement a function with the signature
 * "String yourvar_argnames(int)" to provide names for each of the parameters.
 * The integer passed in is the argument number. Return the same name (i.e.
 * "item") for infinite lists.<br>
 * - You can implement a function with the signature "String[] yourvar_deps()"
 * to provide a list of other prerequisites for this var. You will be guaranteed
 * that the deps are committed before your var, or else a configurationexception
 * will be thrown if a prerequsite was unset. (Note that infinite cycles are not
 * checked, so be careful.)<br>
 */
public final class ConfigurationBuffer
{
    public ConfigurationBuffer(Class<? extends Configuration> configClass)
    {
        this(configClass, new HashMap<String, String>());
    }

    public ConfigurationBuffer(Class<? extends Configuration> configClass, Map<String, String> aliases)
    {
        this(configClass, aliases, null);
    }

    /**
     * Create a configuration buffer with an optional filter. The filter can be
     * used to remove unwanted options from a super class.
     * 
     * @param filter if null there is no filter, otherwise the set of
     * configuration options is filtered.
     */
    public ConfigurationBuffer(Class<? extends Configuration> configClass, Map<String, String> aliases, IConfigurationFilter filter)
    {
        this.configClass = configClass;
        this.varMap = new HashMap<String, List<ConfigurationValue>>();
        this.committed = new HashSet<String>();

        loadCache(configClass, filter);
        assert (varCache.size() > 0) : "coding error: nothing was configurable in the provided object!";
        for (Map.Entry<String, String> e : aliases.entrySet())
        {
            addAlias(e.getKey(), e.getValue());
        }
    }

    public ConfigurationBuffer(ConfigurationBuffer copyFrom, boolean copyCommitted)
    {
        this.configClass = copyFrom.configClass;
        this.varMap = new HashMap<String, List<ConfigurationValue>>(copyFrom.varMap);
        this.committed = copyCommitted ? new HashSet<String>(copyFrom.committed) : new HashSet<String>();
        this.varCache = copyFrom.varCache; // doesn't change after creation
        this.varList = copyFrom.varList; // doesn't change after creation
        this.tokens = new HashMap<String, String>(copyFrom.tokens);
    }

    public final List<String> dump()
    {
        final List<String> dump = new ArrayList<String>(varCache.size());
        for (final Map.Entry<String, ConfigurationInfo> entry : varCache.entrySet())
        {
            dump.add(entry.getKey() + "," + entry.getValue().toString());
        }
        Collections.sort(dump);
        return dump;
    }

    public void setVar(String var, String val, String source, int line) throws ConfigurationException
    {
        List<String> list = new LinkedList<String>();
        list.add(val);
        setVar(var, list, source, line, null, false);
    }

    public void setVar(String var, List<String> vals, String source, int line) throws ConfigurationException
    {
        setVar(var, vals, source, line, null, false);
    }

    public void setVar(String avar, List<String> vals, String source, int line, String contextPath, boolean append) throws ConfigurationException
    {
        String var = unalias(avar);
        if (!isValidVar(var))
            throw new ConfigurationException.UnknownVariable(var, source, line);

        int argCount = getVarArgCount(var);

        // -1 means unspecified length, its up to the receiving setter to validate.
        if (argCount != -1)
        {
            addAnyDefaultArgValues(var, argCount, vals);

            if (vals.size() != argCount)
            {
                throw new ConfigurationException.IncorrectArgumentCount(argCount, // expected
                        vals.size(), //passed
                var, source, line);
            }
        }

        ConfigurationValue val = new ConfigurationValue(this, var,
                                                         vals, //processValues( var, vals, source, line ),
                                                         source, line, contextPath);
        storeValue(var, val, append);
        committed.remove(var);
    }

    public void clearVar(String avar, String source, int line) throws ConfigurationException
    {
        String var = unalias(avar);
        if (!isValidVar(var))
            throw new ConfigurationException.UnknownVariable(var, source, line);
        varMap.remove(var);
        committed.remove(var);
    }

    /**
     * Remove the configuration values came from the given source.
     * 
     * @param source source name
     * @see CommandLineConfigurator#SOURCE_COMMAND_LINE
     */
    public void clearSourceVars(String source)
    {
        List<String> remove = new LinkedList<String>();
        for (Map.Entry<String, List<ConfigurationValue>> e : varMap.entrySet())
        {
            String var = e.getKey();
            List<ConfigurationValue> vals = e.getValue();

            List<ConfigurationValue> newvals = new LinkedList<ConfigurationValue>();
            for (ConfigurationValue val : vals)
            {
                if (!val.getSource().equals(source))
                {
                    newvals.add(val);
                }
            }
            if (newvals.size() > 0)
                varMap.put(var, newvals);
            else
                remove.add(var);
        }
        for (Iterator<String> it = remove.iterator(); it.hasNext();)
        {
            varMap.remove(it.next());
        }
    }

    public List<String> processValues(String var, List<String> args, String source, int line) throws ConfigurationException
    {
        List<String> newArgs = new LinkedList<String>();
        for (Iterator<String> it = args.iterator(); it.hasNext();)
        {
            String arg = it.next();

            int depth = 100;
            while (depth-- > 0)
            {
                int o = arg.indexOf("${");
                if (o == -1)
                    break;

                int c = arg.indexOf("}", o);

                if (c == -1)
                {
                    throw new ConfigurationException.Token(ConfigurationException.Token.MISSING_DELIMITER,
                                                           null, var, source, line);
                }
                String token = arg.substring(o + 2, c);
                String value = getToken(token);

                if (value == null)
                {
                    if (value == null)

                    {
                        throw new ConfigurationException.Token(ConfigurationException.Token.UNKNOWN_TOKEN,
                                                                token, var, source, line);
                    }

                }
                arg = arg.substring(0, o) + value + arg.substring(c + 1);

            }
            if (depth == 0)
            {
                throw new ConfigurationException.Token(ConfigurationException.Token.RECURSION_LIMIT,
                                                        null, var, source, line);
            }

            newArgs.add(arg);
        }
        return newArgs;
    }

    public void setToken(String token, String value)
    {
        tokens.put(token, value);
    }

    public String getToken(String token)
    {
        if (tokens.containsKey(token))
            return tokens.get(token);
        else
        {
            try
            {
                return System.getProperty(token);
            }
            catch (SecurityException se)
            {
                return null;
            }
        }
    }

    private void storeValue(String avar, ConfigurationValue val, boolean append) throws ConfigurationException
    {
        String var = unalias(avar);
        ConfigurationInfo info = getInfo(var);

        List<ConfigurationValue> vals;
        if (varMap.containsKey(var))
        {
            vals = varMap.get(var);
            assert (vals.size() > 0);
            ConfigurationValue first = vals.get(0);
            if (!append && !first.getSource().equals(val.getSource()))
                vals.clear();
            else if (!info.allowMultiple())
                throw new ConfigurationException.IllegalMultipleSet(
                                                  var,
                                                  val.getSource(), val.getLine());
        }
        else
        {
            vals = new LinkedList<ConfigurationValue>();
            varMap.put(var, vals);
        }
        vals.add(val);
    }

    public List<ConfigurationValue> getVar(String avar)
    {
        String var = unalias(avar);
        return varMap.get(var);
    }

    public Set<String> getVars()
    {
        return varCache.keySet();
    }

    public void merge(ConfigurationBuffer other)
    {
        assert (configClass == other.configClass);
        varMap.putAll(other.varMap);
        committed.addAll(other.committed);
    }

    private final Map<String, List<ConfigurationValue>> varMap; // list of vars that have been set
    private final Set<String> committed; // set of vars committed to backing config
    private final Class<? extends Configuration> configClass; // configuration class
    private Map<String, ConfigurationInfo> varCache // info cache
    = new HashMap<String, ConfigurationInfo>();
    private List<String> requiredList = new LinkedList<String>(); // required vars
    private List<String> varList = new LinkedList<String>(); // list of vars in order they should be set
    private Map<String, String> aliases = new HashMap<String, String>(); // variable name aliases
    private Map<String, String> tokens = new HashMap<String, String>(); // tokens for replacement
    private List<Object[]> positions = new ArrayList<Object[]>();

    private static final String SET_PREFIX = "cfg";
    private static final String GET_PREFIX = "get";
    private static final String INFO_SUFFIX = "Info";

    //-----------------------------------------------
    //

    /**
     * WORKAROUND FOR BUG CMP-396
     * 
     * <p>
     * {@link #c2h(String)} generates option names based on cfgXXX names in
     * {@code Configuration}. Since we collapsed all the sub-configurations into
     * one class, there's no longer a "base name" like "compiler.*" or
     * "compiler.fonts.*". In order to preserve the dotted naming convention, we
     * need to know which "-" separated names are actually dotted names. The
     * {@link #CONVERT_FROM} and {@link #CONVERT_TO} is an <b>ordered</b> lookup
     * table for option group base names. It's order makes sure that the longest
     * possible replacement is done.
     */
    private static final ImmutableList<String> CONVERT_FROM =
            ImmutableList.of(
                    "compiler-fonts-languages-",
                    "compiler-fonts-",
                    "compiler-namespaces-",
                    "compiler-mxml-",
                    "compiler-",
                    "metadata-",
                    "licenses-",
                    "frames-",
                    "runtime-shared-library-settings-");

    private static final ImmutableList<String> CONVERT_TO =
            ImmutableList.of(
                    "compiler.fonts.languages.",
                    "compiler.fonts.",
                    "compiler.namespaces.",
                    "compiler.mxml.",
                    "compiler.",
                    "metadata.",
                    "licenses.",
                    "frames.",
                    "runtime-shared-library-settings.");

    /**
     * convert StudlyCaps or camelCase to hyphenated
     * 
     * @param camel someVar or SomeVar
     * @return hyphen some-var
     */
    protected static String c2h(String camel)
    {
        StringBuilder b = new StringBuilder(camel.length() + 5);
        for (int i = 0; i < camel.length(); ++i)
        {
            char c = camel.charAt(i);
            if (Character.isUpperCase(c))
            {
                if (i != 0)
                    b.append('-');
                b.append(Character.toLowerCase(c));
            }
            else
            {
                b.append(camel.charAt(i));
            }
        }
        final String combined = b.toString();

        for (int i = 0; i < CONVERT_FROM.size(); i++)
        {
            if (combined.startsWith(CONVERT_FROM.get(i)))
            {
                return combined.replaceFirst(CONVERT_FROM.get(i), CONVERT_TO.get(i));
            }
        }
        return combined;
    }

    /**
     * convert hyphenated to StudlyCaps or camelCase
     * 
     * @param hyphenated some-var
     * @return result
     */
    protected static String h2c(String hyphenated, boolean studly)
    {
        StringBuilder b = new StringBuilder(hyphenated.length());
        boolean capNext = studly;
        for (int i = 0; i < hyphenated.length(); ++i)
        {
            char c = hyphenated.charAt(i);
            if (c == '-')
                capNext = true;
            else
            {
                b.append(capNext ? Character.toUpperCase(c) : c);
                capNext = false;
            }
        }
        return b.toString();
    }

    public static String varname(String membername, String basename)
    {
        return ((basename == null) ? membername : (basename + "." + membername));
    }

    private static ConfigurationInfo createInfo(Method setterMethod)
    {
        ConfigurationInfo info = null;

        String infoMethodName = GET_PREFIX + setterMethod.getName().substring(SET_PREFIX.length()) + INFO_SUFFIX;
        String getterMethodName = GET_PREFIX + setterMethod.getName().substring(SET_PREFIX.length());
        @SuppressWarnings("unchecked")
        Class<? extends Configuration> cfgClass = (Class<? extends Configuration>)setterMethod.getDeclaringClass();

        Method infoMethod = null, getterMethod = null;
        if (!setterMethod.isAnnotationPresent(Config.class))
        {
            try
            {
                infoMethod = cfgClass.getMethod(infoMethodName);
    
                if (!Modifier.isStatic(infoMethod.getModifiers()))
                {
                    assert false : ("coding error: " + cfgClass.getName() + "." + infoMethodName + " needs to be static!");
                    infoMethod = null;
                }
    
                info = (ConfigurationInfo)infoMethod.invoke(null, (Object[])null);
    
            }
            catch (SecurityException e)
            {
                e.printStackTrace();
            }
            catch (NoSuchMethodException e)
            {
            }
            catch (IllegalArgumentException e)
            {
                e.printStackTrace();
            }
            catch (IllegalAccessException e)
            {
                e.printStackTrace();
            }
            catch (InvocationTargetException e)
            {
                e.printStackTrace();
            }
        }
        
        if (info == null)
            info = new ConfigurationInfo();

        try
        {
            getterMethod = cfgClass.getMethod(getterMethodName, (Class[])null);
        }
        catch (SecurityException e)
        {
            e.printStackTrace();
        }
        catch (NoSuchMethodException e)
        {
        }
        info.setSetterMethod(setterMethod);
        info.setGetterMethod(getterMethod);

        return info;
    }

    /**
     * load - prefetch all the interesting names into a dictionary so that we
     * can find them again more easily. At the end of this call, we will have a
     * list of every variable and their associated method.
     * 
     * @param filter if null there is no filter, otherwise the set of
     * configuration options is filtered.
     */
    private boolean loadCache(Class<? extends Configuration> cfg, IConfigurationFilter filter)
    {
        int count = 0;

        // First, find all vars at this level.
        for (final Method method : cfg.getMethods())
        {
            if (method.getName().startsWith(SET_PREFIX) ||
                method.isAnnotationPresent(Config.class))
            {
                String configName = null;

                final Class<?>[] pt = method.getParameterTypes();
                assert pt.length > 1 : "Expected at least one parameters on setter.";

                // Collect configuration info from getXXXInfo() static methods.
                final ConfigurationInfo info = createInfo(method);

                // Collect configuration info from annotations.
                final Config config = method.getAnnotation(Config.class);
                if (config != null)
                {
                    info.isAdvanced = config.advanced();
                    info.isHidden = config.hidden();
                    info.isRemoved = config.removed();
                    info.allowMultiple = config.allowMultiple();
                    info.isPath = config.isPath();
                    info.isDisplayed = config.displayed();
                    info.isCompcOnly = config.compcOnly();
                    info.isRequired = config.isRequired();
                    
                    // Argument name generator class
                    final ArgumentNameGenerator argumentNameGeneratorClass = 
                        method.getAnnotation(ArgumentNameGenerator.class);
                    if (argumentNameGeneratorClass != null)
                    {
                        info.argNameGeneratorClass = argumentNameGeneratorClass.value();
                    }
                    else
                    {
                        // Argument names
                        final Arguments arguments = method.getAnnotation(Arguments.class);
                        if (arguments != null)
                            info.argnames = arguments.value();
                    }
                    
                    // Argument count
                    final InfiniteArguments infinite = method.getAnnotation(InfiniteArguments.class);
                    if (infinite != null)
                        info.argcount = ConfigurationInfo.INFINITE_ARGS;

                    // Soft Prerequisites
                    final SoftPrerequisites softPre = method.getAnnotation(SoftPrerequisites.class);
                    if (softPre != null)
                        info.softPrerequisites = softPre.value();
                    
                    // XML element name for configuration
                    final Mapping mapping = method.getAnnotation(Mapping.class);
                    if (mapping != null)
                        configName = Joiner.on(".").skipNulls().join(mapping.value());
                    
                    // Is this a Flex only option?
                    final RoyaleOnly royaleOnly = method.getAnnotation(RoyaleOnly.class);
                    if (royaleOnly != null)
                        info.isRoyaleOnly = true;
                }

                // Fall back to naming convention for configuration names.
                if (configName == null)
                    configName = c2h(method.getName().substring(SET_PREFIX.length()));

                if( filter == null || filter.select(configName) )
                {
                    varCache.put(configName, info);
                    varList.add(configName);
                    if (info.isRequired())
                    {
                        requiredList.add(configName);
                    }
                    ++count;
                }
            }
        }

        assert (count > 0 || filter != null) : "coding error: config class " + cfg.getName() + " did not define any setters or child configs";
        return (count > 0);
    }

    String classToArgName(Class<?> c)
    {
        // we only support builtin classnames!

        String className = c.getName();
        if (className.startsWith("java.lang."))
            className = className.substring("java.lang.".length());

        return className.toLowerCase();
    }

    public ConfigurationInfo getInfo(String avar)
    {
        String var = unalias(avar);
        return varCache.get(var);
    }

    public String getVarArgName(String avar, int argnum)
    {
        String var = unalias(avar);
        ConfigurationInfo info = getInfo(var);

        if (info == null)
        {
            assert false : ("must call isValid to check vars!");
        }

        return info.getArgName(argnum);
    }

    public boolean isValidVar(String avar)
    {
        String var = unalias(avar);
        ConfigurationInfo info = getInfo(var);
        return (info != null);
    }

    public int getVarArgCount(String avar)
    {
        ConfigurationInfo info = getInfo(avar);
        assert (info != null);
        return info.getArgCount();
    }

    /**
     * Add any default values to an argument, if the user did not specify them
     * on the command line.
     * 
     * @param avar the argument variable
     * @param argCount the number of argument values specified
     * @param vals Values to add any default values to
     */
    private void addAnyDefaultArgValues(String avar, int argCount, List<String> vals)
    {
        ConfigurationInfo info = getInfo(avar);
        final int missingArgsCount = argCount - vals.size();
        if (missingArgsCount == 0 || info.getDefaultArgValues() == null)
            return;

        final String[] defaultArgValues = info.getDefaultArgValues();
        final int defaultArgsCount = defaultArgValues.length;
        final int defaultArgsStart = defaultArgsCount - missingArgsCount;
        for (int i = defaultArgsStart; i < defaultArgsCount; i++)
        {
            vals.add(defaultArgValues[i]);
        }
    }

    /**
     * commit - bake the resolved map to the configuration
     * 
     * @param config The configuration to set the buffer variables into.
     * @param problems A collection where configuration problems are reported.
     * 
     * @return true if successful, false otherwise.
     */
    public boolean commit(Object config, Collection<ICompilerProblem> problems)
    {
        assert (config.getClass() == configClass) : 
            ("coding error: configuration " + config.getClass() + " != template " + configClass);
        Set<String> done = new HashSet<String>();
        boolean success = true;
        
        for (Iterator<String> vars = varList.iterator(); vars.hasNext();)
        {
            String var = vars.next();
            if (varMap.containsKey(var))
            {
                try
                {
                    commitVariable(config, var, done);
                }
                catch (ConfigurationException e)
                {
                    problems.add(new ConfigurationProblem(e));
                    success = false;
                }
            }
        }

        for (Iterator<String> reqs = requiredList.iterator(); reqs.hasNext();)
        {
            String req = reqs.next();

            if (!committed.contains(req))
            {
                ConfigurationException e = new ConfigurationException.MissingRequirement(req, null, null, -1);
                problems.add(new ConfigurationProblem(
                        null,
                        -1,
                        -1,
                        -1,
                        -1,
                        e.getMessage()));
                success = false;
            }
        }
        
        return success;
    }

    /**
     * commitVariable - copy a variable out of a state into the final config.
     * This should only be called on variables that are known to exist in the
     * state!
     * 
     * @param var variable name to lookup
     * @param done set of variable names that have been completed so far (for
     * recursion)
     */
    private void commitVariable(Object config, String var, Set<String> done) throws ConfigurationException
    {
        ConfigurationInfo info = getInfo(var);

        setPrerequisites(info.getPrerequisites(), var, done, config, true);
        setPrerequisites(info.getSoftPrerequisites(), var, done, config, false);

        if (committed.contains(var))
            return;

        committed.add(var);
        done.add(var);

        assert (varMap.containsKey(var));
        List<ConfigurationValue> vals = varMap.get(var);

        if (vals.size() > 1)
        {
            assert (info.allowMultiple()); // assumed to have been previously checked
        }
        for (ConfigurationValue val : vals)
        {
            try
            {
                Object[] args = buildArgList(info, val);

                info.getSetterMethod().invoke(config, args);
            }
            catch (Exception e)
            {
                Throwable t = e;

                if (e instanceof InvocationTargetException)
                {
                    t = ((InvocationTargetException)e).getTargetException();
                }

                if (Trace.error)
                    t.printStackTrace();

                if (t instanceof ConfigurationException)
                {
                    throw (ConfigurationException)t;
                }
                else
                {
                    throw new ConfigurationException.OtherThrowable(t, var, val.getSource(), val.getLine());
                }
            }
        }

    }

    private void setPrerequisites(String[] prerequisites, String var, Set<String> done, Object config, boolean required)
            throws ConfigurationException
    {
        if (prerequisites != null)
        {
            for (int p = 0; p < prerequisites.length; ++p)
            {
                String depvar = prerequisites[p];

                // Dependencies can only go downward.
                int dot = var.lastIndexOf('.');

                if (dot >= 0)
                {
                    String car = var.substring(0, dot);
                    //String cdr = var.substring( dot + 1 );

                    String newDepvar = car + "." + depvar;

                    // Since in royale we have collapsed sub-configurations into one
                    // configuration, some options that were in sub-configurations now
                    // have prerequisites on options in the same configuration. We
                    // need to keep the old configuration mappings so old configurations
                    // options will still work. So a simple thing we can do is if the 
                    // dependency variable is invalid (presumably because the 
                    // dependency is really on a parent configuration option), 
                    // then use the dependency as is depvar) and see if it is 
                    // valid. If depvar ends up not being valid then set depvar
                    // to newDepvar so error reporting isn't changed by the new
                    // fall-back behavior.
                    if (isValidVar(newDepvar) || !isValidVar(depvar))
                        depvar = newDepvar;

                }

                if (!done.contains(depvar))
                {
                    if (!isValidVar(depvar))
                    {
                        assert false : ("invalid " + var + " dependency " + depvar);
                        continue;
                    }
                    if (varMap.containsKey(depvar))
                    {
                        commitVariable(config, depvar, done);
                    }
                    else if (required && !committed.contains(depvar))
                    {
                        // TODO - can we get source/line for this?
                        throw new ConfigurationException.MissingRequirement(depvar, var, null, -1);
                    }
                }
            }
        }
    }

    private String[] constructStringArray(List<String> args)
    {
        String[] sa = new String[args.size()];

        int i = 0;
        for (Iterator<String> it = args.iterator(); it.hasNext();)
            sa[i++] = it.next();

        return sa;
    }

    private Object constructValueObject(ConfigurationInfo info, ConfigurationValue cv) throws ConfigurationException
    {
        try
        {
            Class<?>[] pt = info.getSetterMethod().getParameterTypes();
            assert (pt.length == 2); // assumed to be checked upstream

            Object o = pt[1].newInstance();

            Field[] fields = pt[1].getFields();

            assert (fields.length == cv.getArgs().size()); // assumed to be checked upstream

            Iterator<String> argsit = cv.getArgs().iterator();
            for (int f = 0; f < fields.length; ++f)
            {
                String val = (String)argsit.next();
                Object valobj = null;
                Class<?> fc = fields[f].getType();

                assert (info.getArgType(f) == fc);
                assert (info.getArgName(f).equals(ConfigurationBuffer.c2h(fields[f].getName())));

                if (fc == String.class)
                {
                    valobj = val;
                }
                else if ((fc == Boolean.class) || (fc == boolean.class))
                {
                    // TODO - Boolean.valueOf is pretty lax.  Maybe we should restrict to true/false?
                    valobj = Boolean.valueOf(val);
                }
                else if ((fc == Integer.class) || (fc == int.class))
                {
                    valobj = Integer.decode(val);
                }
                else if ((fc == Long.class) || (fc == long.class))
                {
                    valobj = Long.decode(val);
                }
                else
                {
                    assert false; // should have checked any other condition upstream!
                }
                fields[f].set(o, valobj);
            }

            return o;
        }
        catch (InstantiationException e)
        {
            assert false : ("coding error: unable to instantiate value object when trying to set var " + cv.getVar());
            throw new ConfigurationException.OtherThrowable(e, cv.getVar(), cv.getSource(), cv.getLine());

        }
        catch (IllegalAccessException e)
        {
            assert false : ("coding error: " + e + " when trying to set var " + cv.getVar());
            throw new ConfigurationException.OtherThrowable(e, cv.getVar(), cv.getSource(), cv.getLine());
        }
    }

    protected static boolean isSupportedSimpleType(Class<?> c)
    {
        return ((c == String.class)
                || (c == Integer.class) || (c == int.class)
                || (c == Long.class) || (c == long.class)
                || (c == Boolean.class) || (c == boolean.class));
    }

    protected static boolean isSupportedListType(Class<?> c)
    {
        return ((c == List.class) || (c == String[].class));
    }

    protected static boolean isSupportedValueType(Class<?> c)
    {
        if (isSupportedSimpleType(c))
            return false;

        Field[] fields = c.getFields();

        for (int f = 0; f < fields.length; ++f)
        {
            if (!isSupportedSimpleType(fields[f].getType()))
                return false;
        }
        return true;
    }

    private Object[] buildArgList(ConfigurationInfo info, ConfigurationValue val) throws ConfigurationException
    {
        Method setter = info.getSetterMethod();

        Class<?>[] pt = setter.getParameterTypes();

        List<String> args = processValues(val.getVar(), val.getArgs(), val.getSource(), val.getLine());

        if (info.getArgCount() == -1)
        {
            if (pt.length != 2)
            {
                assert false : ("coding error: unlimited length setter " + val.getVar() + " must take a single argument of type List or String[]");
                return null;
            }
            else if (List.class.isAssignableFrom(pt[1]))
            {
                return new Object[] {val, args};
            }
            else if (String[].class.isAssignableFrom(pt[1]))
            {
                return new Object[] {val, constructStringArray(args)};
            }
            else
            {
                assert false : ("coding error: unlimited length setter " + val.getVar() + " must take a single argument of type List or String[]");
                return null;
            }
        }
        else
        {
            assert (pt.length > 1) : ("coding error: config setter " + val.getVar() + " must accept at least one argument");
            // ok, we first check to see if the signature of their setter accepts a list.

            if (pt.length == 2)
            {
                // a variety of specialty setters here...

                if (List.class.isAssignableFrom(pt[1]))
                {
                    return new Object[] {val, args};
                }
                else if (String[].class == pt[1])
                {
                    return new Object[] {val, constructStringArray(args)};
                }
                else if (isSupportedValueType(pt[1]))
                {
                    return new Object[] {val, constructValueObject(info, val)};
                }
            }

            // otherwise, they must have a matching size parm list as the number of args passed in.

            assert (pt.length == (args.size() + 1)) : ("coding error: config setter " + val.getVar() + " does not have " + args.size() + " parameters!");

            Object[] pa = new Object[pt.length];

            pa[0] = val;

            for (int p = 1; p < pt.length; ++p)
            {
                String arg = args.get(p - 1);
                if (pt[p].isAssignableFrom(String.class))
                {
                    pa[p] = arg;
                }
                else if ((pt[p] == int.class) || (pt[p] == Integer.class))
                {
                    try
                    {
                        pa[p] = Integer.decode(arg);

                    }
                    catch (Exception e)
                    {
                        throw new ConfigurationException.TypeMismatch(ConfigurationException.TypeMismatch.INTEGER,
                                                                       arg, val.getVar(), val.getSource(), val.getLine());
                    }
                }
                else if ((pt[p] == long.class) || (pt[p] == Long.class))
                {
                    try
                    {
                        pa[p] = Long.decode(arg);

                    }
                    catch (Exception e)
                    {
                        throw new ConfigurationException.TypeMismatch(
                                ConfigurationException.TypeMismatch.LONG,
                                arg, val.getVar(), val.getSource(), val.getLine());
                    }
                }
                else if ((pt[p] == boolean.class) || (pt[p] == Boolean.class))
                {
                    try
                    {
                        arg = arg.trim().toLowerCase();
                        if (arg.equals("true") || arg.equals("false"))
                        {
                            pa[p] = Boolean.valueOf(arg);
                        }
                        else
                        {
                            throw new ConfigurationException.TypeMismatch(
                                    ConfigurationException.TypeMismatch.BOOLEAN, arg, val.getVar(), val.getSource(), val.getLine());
                        }
                    }
                    catch (Exception e)
                    {
                        throw new ConfigurationException.TypeMismatch(
                                ConfigurationException.TypeMismatch.BOOLEAN, arg, val.getVar(), val.getSource(), val.getLine());
                    }
                }
                else
                {
                    assert false : ("coding error: " + val.getVar() + " setter argument " + p + " is not a supported type");
                }
            }

            return pa;
        }
    }

    public void addAlias(String alias, String var)
    {
        if (!isValidVar(var))
        {
            assert false : ("coding error: can't bind alias " + alias + " to nonexistent var " + var);
            return;
        }
        if (aliases.containsKey(alias))
        {
            assert false : ("coding error: alias " + alias + " already defined as " + aliases.get(alias));
            return;
        }
        if (varCache.containsKey(alias))
        {
            assert false : ("coding error: can't define alias " + alias + ", it already exists as a var");
            return;
        }

        aliases.put(alias, var);
    }

    public Map<String, String> getAliases()
    {
        return aliases;
    }

    public String unalias(String var)
    {
        String realvar = aliases.get(var);
        return (realvar == null) ? var : realvar;
    }

    public String peekSimpleConfigurationVar(String avar) throws ConfigurationException
    {
        String val = null;
        List<ConfigurationValue> valList = getVar(avar);
        if (valList != null)
        {
            ConfigurationValue cv = (ConfigurationValue)valList.get(0);
            List<String> args = processValues(avar, cv.getArgs(), cv.getSource(), cv.getLine());
            val = args.get(0);
        }
        return val;
    }

    public List<ConfigurationValue> peekConfigurationVar(String avar) throws ConfigurationException
    {
        List<ConfigurationValue> srcList = getVar(avar);
        if (srcList == null)
            return null;

        List<ConfigurationValue> dstList = new LinkedList<ConfigurationValue>();
        for (ConfigurationValue srcVal : srcList)
        {
            List<String> args = processValues(avar, srcVal.getArgs(), srcVal.getSource(), srcVal.getLine());

            ConfigurationValue dstVal = new ConfigurationValue(srcVal.getBuffer(), avar, args, srcVal.getSource(), srcVal.getLine(), srcVal.getContext());
            dstList.add(dstVal);
        }
        return dstList;
    }

    public void addPosition(String var, int iStart, int iEnd)
    {
        positions.add(new Object[] {var, new Integer(iStart), new Integer(iEnd)});
    }

    public List<Object[]> getPositions()
    {
        return positions;
    }

    public static List<String> formatText(String input, int columns)
    {
        ArrayList<String> lines = new ArrayList<String>();

        if ((input == null) || (input.length() == 0))
            return lines;

        int current = 0;
        int lineStart = -1;
        int lineEnd = -1;
        int wordStart = -1;
        int wordEnd = -1;
        boolean start = true;
        boolean preserve = true;

        while (true)
        {
            if (current < input.length())
            {
                boolean newline = input.charAt(current) == '\n';
                boolean printable = (preserve && !newline) || !Character.isWhitespace(input.charAt(current));

                if (start) // find a word
                {
                    if (printable)
                    {
                        if (lineStart == -1)
                        {
                            lineStart = current;
                        }
                        wordStart = current;
                        start = false;
                    }
                    else
                    {
                        if (newline && lineStart != -1)
                        {
                            lines.add(input.substring(lineStart, current));
                            lineStart = -1;
                        }
                        else if (newline)
                        {
                            lines.add("");
                        }
                        ++current;
                    }
                }
                else
                // have a word
                {
                    preserve = false;
                    if (printable)
                    {
                        ++current;
                    }
                    else
                    {
                        wordEnd = current;
                        if (lineEnd == -1)
                        {
                            lineEnd = current;
                        }

                        // two possibilities; if the new word fits in the current line length
                        // without being too many columns, leave on current line.
                        // otherwise, set it as the start of a new line.

                        if (wordEnd - lineStart < columns)
                        {
                            if (newline)
                            {
                                lines.add(input.substring(lineStart, current));
                                lineStart = -1;
                                lineEnd = -1;
                                wordStart = -1;
                                start = true;
                                preserve = true;
                                ++current;
                            }
                            else
                            {
                                // we have room to add the current word to this line, find new word
                                start = true;
                                lineEnd = current;
                            }
                        }
                        else
                        {
                            // current word pushes things beyond the requested column limit,
                            // dump current text
                            lines.add(input.substring(lineStart, lineEnd));
                            lineStart = wordStart;
                            lineEnd = -1;
                            wordStart = -1;
                            start = true;
                            if (newline)
                                preserve = true;
                        }
                    }
                }
            }
            else
            // we're done
            {
                // a) no line yet, so don't do anything
                // b) have line and new word would push over edge, need two lines
                // c) have line and current word fits, need one line
                // d) only one word and its too long anyway, need one line

                if (lineStart != -1) // we have a line in progress
                {
                    wordEnd = current;
                    if (lineEnd == -1)
                        lineEnd = current;

                    if (((wordEnd - lineStart) < columns) // current word fits
                        || (wordEnd == lineEnd)) // or one long word
                    {
                        lineEnd = wordEnd;
                        lines.add(input.substring(lineStart, wordEnd));
                    }
                    else
                    // didn't fit, multiple words
                    {
                        lines.add(input.substring(lineStart, lineEnd));
                        lines.add(input.substring(wordStart, wordEnd));
                    }
                }
                break;
            }
        }
        return lines;
    }

    /**
     * For debugging only.
     * <p>
     * Produces an alphabetized list of this buffer's configuration options and their values.
     * An option such as
     * <pre>
     * -foo=aaa,bbb -foo+=ccc
     * </pre>
     * will appear as
     * <pre>
     * foo=aaa,bbb;ccc
     * </pre>
     */
    @Override
    public String toString()
    {
        StringBuffer sb = new StringBuffer();
        
        String[] variables = varMap.keySet().toArray(new String[0]);
        Arrays.sort(variables);
        
        for (String var : variables)
        {
            sb.append(var);
            sb.append("=");

            ArrayList<String> commaSeparatedValues = new ArrayList<String>();
            for (ConfigurationValue cv : varMap.get(var))
            {
                List<String> args = cv.getArgs();
                String joinedArgs = Joiner.on(',').join(args);
                commaSeparatedValues.add(joinedArgs);
            }
            String rhs = Joiner.on(';').join(commaSeparatedValues);
            sb.append(rhs);
            
            sb.append('\n');
        }

        return sb.toString();
    }
}
