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

import java.util.Arrays;
import java.util.List;
import java.util.LinkedList;
import java.util.TreeSet;
import java.util.Set;
import java.util.Iterator;
import java.util.HashSet;
import java.util.Map;
import java.util.HashMap;
import java.io.File;

import com.google.common.base.Joiner;

import org.apache.royale.compiler.Messages;
import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.internal.config.localization.LocalizationManager;

/**
 * A utility class, which is used to parse an array of command line args and
 * populate a ConfigurationBuffer. It also contains some associated methods like
 * brief() and usage(). A counterpart of FileConfigurator and
 * SystemPropertyConfigurator.
 */
public class CommandLineConfigurator
{
    public static final String SOURCE_COMMAND_LINE = "command line";

    /**
     * parse - buffer up configuration vals from the command line
     * 
     * @param buffer the configuration buffer to hold the results
     * @param defaultvar the variable name where the trailing loose args go
     * @param args the command line
     */
    public static void parse(final ConfigurationBuffer buffer,
                              final String defaultvar,
                              final String[] args)
            throws ConfigurationException
    {
        // "no-default-arg" means the application does not have a default var.
        assert defaultvar == null || buffer.isValidVar(defaultvar) || "no-default-arg".equals(defaultvar) : "coding error: config must provide default var " + defaultvar;

        Map<String, String> aliases = getAliases(buffer);
        final int START = 1;
        final int ARGS = 2;
        final int EXEC = 3;
        final int DONE = 4;

        int i = 0, iStart = 0, iEnd = 0;
        String var = null;
        int varArgCount = -2;
        List<String> argList = new LinkedList<String>();
        Set<String> vars = new HashSet<String>();
        boolean append = false;
        boolean dash = true;

        int mode = START;

        while (mode != DONE)
        {
            switch (mode)
            {
                case START:
                {
                    iStart = i;

                    if (args.length == i)
                    {
                        mode = DONE;
                        break;
                    }
                    // expect -var, --, or the beginning of default args

                    mode = ARGS;
                    varArgCount = -2;

                    if (args[i].equals("--"))
                    {
                        dash = false;
                        if (defaultvar != null)
                            var = defaultvar;
                        else
                            mode = START;
                        ++i;
                    }
                    else if (dash && args[i].startsWith("+"))
                    {
                        String token = null;
                        int c = (args[i].length() > 1 && args[i].charAt(1) == '+') ? 2 : 1; // gnu-style?

                        int equals = args[i].indexOf('=');
                        String rest = null;
                        if (equals != -1)
                        {
                            rest = args[i].substring(equals + 1);
                            token = args[i++].substring(c, equals);
                        }
                        else
                        {
                            token = args[i++].substring(c);
                        }
                        if (equals != -1)
                        {
                            iEnd = i;
                            buffer.setToken(token, rest);
                            buffer.addPosition(token, iStart, iEnd);
                        }
                        else
                        {
                            if (i == args.length)
                            {
                                throw new ConfigurationException.Token(ConfigurationException.Token.INSUFFICIENT_ARGS,
                                                                        token, var, source, -1);
                            }
                            rest = args[i++];
                            iEnd = i;
                            buffer.setToken(token, rest);
                            buffer.addPosition(token, iStart, iEnd);
                        }
                        mode = START;
                        break;
                    }
                    else if (dash && isAnArgument(args[i]))
                    {
                        int c = (args[i].length() > 1 && args[i].charAt(1) == '-') ? 2 : 1; // gnu-style?

                        int plusequals = args[i].indexOf("+=");
                        int equals = args[i].indexOf('=');
                        String rest = null;
                        if (plusequals != -1)
                        {
                            rest = args[i].substring(plusequals + 2);
                            var = args[i++].substring(c, plusequals);
                            append = true;
                        }
                        else if (equals != -1)
                        {
                            rest = args[i].substring(equals + 1);
                            var = args[i++].substring(c, equals);
                        }
                        else
                        {
                            var = args[i++].substring(c);
                        }

                        if (aliases.containsKey(var))
                            var = aliases.get(var);

                        if (!buffer.isValidVar(var))
                        {
                            throw new ConfigurationException.UnknownVariable(var, source, -1);
                        }

                        if (equals != -1)
                        {
                            if ((rest == null) || (rest.length() == 0))
                            {
                                varArgCount = -1;
                                mode = EXEC;
                            }
                            else
                            {
                                String seps = null;
                                if (buffer.getInfo(var).isPath())
                                {
                                    seps = "[," + File.pathSeparatorChar + "]";
                                }
                                else
                                {
                                    seps = ",";
                                }

                                String[] tokens = rest.split(seps);
                                argList.addAll(Arrays.asList(tokens));
                                varArgCount = buffer.getVarArgCount(var);
                                mode = EXEC;
                            }
                        }

                    }
                    else
                    {
                        // asdoc sets default var as no-default-arg - it has no default vars
                        if (defaultvar != null && !defaultvar.equals("no-default-arg"))
                        {
                            // don't increment i, let ARGS pick it up.
                            var = defaultvar;
                        }
                        else
                        {
                            throw new ConfigurationException.UnexpectedDefaults(null, null, -1);
                        }
                    }
                    break;
                }
                case ARGS:
                {
                    if (varArgCount == -2)
                    {
                        if (isBoolean(buffer, var))
                        {
                            varArgCount = 0;
                            mode = EXEC;
                            break;
                        }
                        else
                        {
                            varArgCount = buffer.getVarArgCount(var);
                        }
                    }
                    assert varArgCount >= -1; // just in case the getVarArgCount author was insane.

                    if (args.length == i)
                    {
                        mode = EXEC;
                        break;
                    }

                    boolean greedy = buffer.getInfo(var).isGreedy();

                    // accumulating non-command arguments...

                    // check for a terminator on our accumulated parameter list
                    if (!greedy && dash && isAnArgument(args[i]))
                    {
                        if (varArgCount == -1)
                        {
                            // we were accumulating an unlimited set of args, a new var terminates that.
                            mode = EXEC;
                            break;
                        }
                        throw new ConfigurationException.IncorrectArgumentCount(varArgCount, argList.size(), var, source, -1);
                    }

                    argList.add(args[i++]);
                    if (argList.size() == varArgCount)
                    {
                        mode = EXEC;
                    }

                    break;
                }
                case EXEC:
                {
                    if ((varArgCount != -1) && (argList.size() != varArgCount))
                    {
                        throw new ConfigurationException.IncorrectArgumentCount(varArgCount, argList.size(), var, source, -1);
                    }
                    if (varArgCount == 0) // boolean flag fakery...
                        argList.add("true");

                    if (vars.contains(var))
                    {
                        if ((defaultvar != null) && var.equals(defaultvar))
                        {
                            // we could perhaps accumulate the defaults spread out through
                            // the rest of the flags, but for now we'll call this illegal.
                            throw new ConfigurationException.InterspersedDefaults(var, source, -1);
                        }
                    }
                    iEnd = i;
                    buffer.setVar(var, new LinkedList<String>(argList), source, -1, null, append);
                    buffer.addPosition(var, iStart, iEnd);
                    append = false;
                    vars.add(var);
                    argList.clear();
                    mode = START;
                    break;
                }
                case DONE:
                {
                    assert false;
                    break;
                }
            }
        }
    }

    /**
     * Given a string like "-foo" or "-5" or "-123.mxml", this determines
     * whether the string is an argument or... not an argument (e.g. numeral)
     */
    private static boolean isAnArgument(final String arg)
    {
        return (arg.startsWith("-") &&
                // if the first character after a dash is numeric, this is not
                // an argument, it is a parameter (and therefore non-terminating)
                (arg.length() > 1) && !Character.isDigit(arg.charAt(1)));
    }

    private static Map<String, String> getAliases(ConfigurationBuffer buffer)
    {
        Map<String, String> aliases = new HashMap<String, String>();
        aliases.putAll(buffer.getAliases());
        for (final String varname : buffer.getVars())
        {
            if (varname.indexOf('.') == -1)
                continue;

            String leafname = varname.substring(varname.lastIndexOf('.') + 1);
            if (aliases.containsKey(leafname))
                continue;
            aliases.put(leafname, varname);
        }

        return aliases;
    }

    private static boolean isBoolean(ConfigurationBuffer buffer, String var)
    {
        ConfigurationInfo info = buffer.getInfo(var);

        if (info.getArgCount() > 1)
            return false;

        Class<?> c = info.getArgType(0);

        return ((c == boolean.class) || (c == Boolean.class));
    }

    public static String brief(String program, String defaultvar, LocalizationManager l10n, String l10nPrefix)
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("defaultVar", defaultvar);
        params.put("program", program);
        return l10n.getLocalizedTextString(l10nPrefix + ".Brief", params);
    }

    public static String usage(String program, String defaultVar, ConfigurationBuffer cfgbuf, Set<String> keywords, LocalizationManager lmgr, String l10nPrefix)
    {
        boolean isCompc = program.contains("compc");
        Map<String, String> aliases = getAliases(cfgbuf);
        Map<String, String> sesaila = new HashMap<String, String>();
        for (Iterator<Map.Entry<String, String>> it = aliases.entrySet().iterator(); it.hasNext();)
        {
            Map.Entry<String, String> e = it.next();
            sesaila.put(e.getValue(), e.getKey());
        }

        TreeSet<String> printSet = new TreeSet<String>();

        boolean all = false;
        boolean advanced = false;
        boolean details = false;
        boolean syntax = false;
        boolean printaliases = false;

        // figure out behavior..
        Set<String> newSet = new HashSet<String>();
        for (Iterator<String> kit = keywords.iterator(); kit.hasNext();)
        {
            String keyword = kit.next();

            if (keyword.equals("list"))
            {
                all = true;
                newSet.add("*");
            }
            else if (keyword.equals("advanced"))
            {
                advanced = true;
                if (keywords.size() == 1)
                {
                    all = true;
                    newSet.add("*");
                }
            }
            else if (keyword.equals("details"))
            {
                details = true;
            }
            else if (keyword.equals("syntax"))
            {
                syntax = true;
            }
            else if (keyword.equals("aliases"))
            {
                printaliases = true;
            }
            else
            {
                details = true;
                newSet.add(keyword);
            }
        }
        if (syntax)
        {
            final List<String> lines = ConfigurationBuffer.formatText(getSyntaxDescription(program, defaultVar, advanced, lmgr, l10nPrefix), 78);
            return Joiner.on("\n").join(lines);
        }
        keywords = newSet;

        // accumulate set to print
        for (Iterator<String> kit = keywords.iterator(); kit.hasNext();)
        {
            String keyword = kit.next().toLowerCase();

            for (final String var : cfgbuf.getVars())
            {
                ConfigurationInfo info = cfgbuf.getInfo(var);
                
                // If the client is not "compc", skip "compc-only" options.
                if (info.isCompcOnly && !isCompc)
                    continue;
                
                String description = getDescription(cfgbuf, var, lmgr, l10nPrefix);

                if ((all
                        || (var.indexOf(keyword) != -1)
                        || ((description != null) && (description.toLowerCase().indexOf(keyword) != -1))
                        || (keyword.matches(var))
                        || ((sesaila.get(var) != null) && (sesaila.get(var)).indexOf(keyword) != -1))
                     && (!info.isHidden())
                     && (!info.isRemoved())
                     && (advanced || !info.isAdvanced()))
                {
                    if (printaliases && sesaila.containsKey(var))
                        printSet.add(sesaila.get(var));
                    else
                        printSet.add(var);
                }
                else
                {
                    /*
                     * for (int i = 0; i < info.getAliases().length; ++i) {
                     * String alias = info.getAliases()[i]; if (alias.indexOf(
                     * keyword ) != -1) { printSet.add( var ); } }
                     */
                }
            }
        }

        StringBuilder output = new StringBuilder(1024);

        if (printSet.size() == 0)
        {
            String nkm = lmgr.getLocalizedTextString(l10nPrefix + ".NoKeywordsMatched");
            output.append(nkm);
            output.append("\n");
        }
        else
            for (Iterator<String> it = printSet.iterator(); it.hasNext();)
            {
                String avar = it.next();
                String var = avar;
                if (aliases.containsKey(avar))
                    var = aliases.get(avar);

                ConfigurationInfo info = cfgbuf.getInfo(var);
                assert info != null;

                output.append("-");
                output.append(avar);

                int count = cfgbuf.getVarArgCount(var);
                if ((count >= 1) && (!isBoolean(cfgbuf, var)))
                {
                    for (int i = 0; i < count; ++i)
                    {
                        output.append(" <");
                        output.append(cfgbuf.getVarArgName(var, i));
                        output.append(">");
                    }
                }
                else if (count == -1)
                {
                    String last = "";
                    for (int i = 0; i < 5; ++i)
                    {
                        String argname = cfgbuf.getVarArgName(var, i);
                        if (!argname.equals(last))
                        {
                            output.append(" [");
                            output.append(argname);
                            output.append("]");
                            last = argname;
                        }
                        else
                        {
                            output.append(" [...]");
                            break;
                        }
                    }
                }

                output.append("\n");

                if (details)
                {
                    StringBuilder description = new StringBuilder(160);
                    if (printaliases)
                    {
                        if (aliases.containsKey(avar))
                        {
                            String fullname = lmgr.getLocalizedTextString(l10nPrefix + ".FullName");
                            description.append(fullname);
                            description.append(" -");
                            description.append(aliases.get(avar));
                            description.append("\n");
                        }
                    }
                    else if (sesaila.containsKey(var))
                    {
                        String alias = lmgr.getLocalizedTextString(l10nPrefix + ".Alias");
                        description.append(alias);
                        description.append(" -");
                        description.append(sesaila.get(var));
                        description.append("\n");
                    }

                    String d = getDescription(cfgbuf, var, lmgr, l10nPrefix);
                    if (var.equals("help") && (printSet.size() > 2))
                    {
                        String helpKeywords = lmgr.getLocalizedTextString(l10nPrefix + ".HelpKeywords");
                        description.append(helpKeywords);
                    }
                    else if (d != null)
                        description.append(d);

                    String flags = "";
                    if (info.isAdvanced())
                    {
                        String advancedString = lmgr.getLocalizedTextString(l10nPrefix + ".Advanced");
                        flags += (((flags.length() == 0) ? " (" : ", ") + advancedString);
                    }
                    if (info.allowMultiple())
                    {
                        String repeatableString = lmgr.getLocalizedTextString(l10nPrefix + ".Repeatable");
                        flags += (((flags.length() == 0) ? " (" : ", ") + repeatableString);
                    }
                    if ((defaultVar != null) && var.equals(defaultVar))
                    {
                        String defaultString = lmgr.getLocalizedTextString(l10nPrefix + ".Default");
                        flags += (((flags.length() == 0) ? " (" : ", ") + defaultString);
                    }
                    if (info.isRoyaleOnly())
                    {
                        String royaleOnlylString = Messages.getString("RoyaleOnly");
                        flags += (((flags.length() == 0) ? " (" : ", ") + royaleOnlylString);
                    }
                    if (flags.length() != 0)
                    {
                        flags += ")";
                    }
                    description.append(flags);

                    List<String> descriptionLines = ConfigurationBuffer.formatText(description.toString(), 70);

                    for (final String next : descriptionLines)
                    {
                        output.append("    ");
                        output.append(next);
                        output.append("\n");
                    }
                }
            }
        return output.toString();
    }

    public static String getDescription(ConfigurationBuffer buffer, String var, LocalizationManager l10n, String l10nPrefix)
    {
        String key = (l10nPrefix == null) ? var : (l10nPrefix + "." + var);
        String description = l10n.getLocalizedTextString(key, null);

        return description;
    }

    public static String getSyntaxDescription(String program, String defaultVar, boolean advanced, LocalizationManager l10n, String l10nPrefix)
    {
        Map<String, Object> params = new HashMap<String, Object>();
        params.put("defaultVar", defaultVar);
        params.put("program", program);

        String key = l10nPrefix + "." + (advanced ? "AdvancedSyntax" : "Syntax");
        String text = l10n.getLocalizedTextString(key, params);

        if (text == null)
        {
            text = "No syntax help available, try '-help list' to list available configuration variables.";
            assert false : "Localized text for syntax description not found!";
        }
        return text;
    }

    public static final String source = SOURCE_COMMAND_LINE;
}
