/*
 * 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.felix.gogo.options;

import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * Yet another GNU long options parser. This one is configured by parsing its Usage string.
 */
public class Options implements Option
{
    public static void main(String[] args)
    {
        final String[] usage = {
                "test - test Options usage",
                "  text before Usage: is displayed when usage() is called and no error has occurred.",
                "  so can be used as a simple help message.",
                "",
                "Usage: testOptions [OPTION]... PATTERN [FILES]...",
                "  Output control: arbitary non-option text can be included.",
                "  -? --help                show help",
                "  -c --count=COUNT         show COUNT lines",
                "  -h --no-filename         suppress the prefixing filename on output",
                "  -q --quiet, --silent     suppress all normal output",
                "     --binary-files=TYPE   assume that binary files are TYPE",
                "                           TYPE is 'binary', 'text', or 'without-match'",
                "  -I                       equivalent to --binary-files=without-match",
                "  -d --directories=ACTION  how to handle directories (default=skip)",
                "                           ACTION is 'read', 'recurse', or 'skip'",
                "  -D --devices=ACTION      how to handle devices, FIFOs and sockets",
                "                           ACTION is 'read' or 'skip'",
                "  -R, -r --recursive       equivalent to --directories=recurse" };

        Option opt = Options.compile(usage).parse(args);

        if (opt.isSet("help"))
        {
            opt.usage(); // includes text before Usage:
            return;
        }

        if (opt.args().isEmpty())
        {
            throw opt.usageError("PATTERN not specified");
        }
        System.out.println(opt);
        if (opt.isSet("count"))
        {
            System.out.println("count = " + opt.getNumber("count"));
        }
        System.out.println("--directories specified: " + opt.isSet("directories"));
        System.out.println("directories=" + opt.get("directories"));
    }

    public static final String NL = System.getProperty("line.separator", "\n");

    // Note: need to double \ within ""
    private static final String regex = "(?x)\\s*" + "(?:-([^-]))?" + // 1: short-opt-1
        "(?:,?\\s*-(\\w))?" + // 2: short-opt-2
        "(?:,?\\s*--(\\w[\\w-]*)(=\\w+)?)?" + // 3: long-opt-1 and 4:arg-1
        "(?:,?\\s*--(\\w[\\w-]*))?" + // 5: long-opt-2
        ".*?(?:\\(default=(.*)\\))?\\s*"; // 6: default

    private static final int GROUP_SHORT_OPT_1 = 1;
    private static final int GROUP_SHORT_OPT_2 = 2;
    private static final int GROUP_LONG_OPT_1 = 3;
    private static final int GROUP_ARG_1 = 4;
    private static final int GROUP_LONG_OPT_2 = 5;
    private static final int GROUP_DEFAULT = 6;

    private final Pattern parser = Pattern.compile(regex);
    private final Pattern uname = Pattern.compile("^Usage:\\s+(\\w+)");

    private final Map<String, Boolean> unmodifiableOptSet;
    private final Map<String, Object> unmodifiableOptArg;
    private final Map<String, Boolean> optSet = new HashMap<>();
    private final Map<String, Object> optArg = new HashMap<>();

    private final Map<String, String> optName = new HashMap<>();
    private final Map<String, String> optAlias = new HashMap<>();
    private final List<Object> xargs = new ArrayList<>();
    private List<String> args = null;

    private static final String UNKNOWN = "unknown";
    private String usageName = UNKNOWN;
    private int usageIndex = 0;

    private final String[] spec;
    private final String[] gspec;
    private final String defOpts;
    private final String[] defArgs;
    private PrintStream errStream = System.err;
    private String error = null;

    private boolean optionsFirst = false;
    private boolean stopOnBadOption = false;

    public static Option compile(String[] optSpec)
    {
        return new Options(optSpec, null, null);
    }

    public static Option compile(String optSpec)
    {
        return compile(optSpec.split("\\n"));
    }

    public static Option compile(String[] optSpec, Option gopt)
    {
        return new Options(optSpec, null, gopt);
    }

    public static Option compile(String[] optSpec, String[] gspec)
    {
        return new Options(optSpec, gspec, null);
    }

    public Option setStopOnBadOption(boolean stopOnBadOption)
    {
        this.stopOnBadOption = stopOnBadOption;
        return this;
    }

    public Option setOptionsFirst(boolean optionsFirst)
    {
        this.optionsFirst = optionsFirst;
        return this;
    }

    public boolean isSet(String name)
    {
        if (!optSet.containsKey(name))
        {
            throw new IllegalArgumentException("option not defined in spec: " + name);
        }
        return optSet.get(name);
    }

    public Object getObject(String name)
    {
        if (!optArg.containsKey(name))
        {
            throw new IllegalArgumentException("option not defined with argument: " + name);
        }
        List<Object> list = getObjectList(name);

        return list.isEmpty() ? "" : list.get(list.size() - 1);
    }

    @SuppressWarnings("unchecked")
    public List<Object> getObjectList(String name)
    {
        List<Object> list;
        Object arg = optArg.get(name);

        if (arg == null)
        {
            throw new IllegalArgumentException("option not defined with argument: " + name);
        }

        if (arg instanceof String)
        { // default value
            list = new ArrayList<>();
            if (!"".equals(arg))
            {
                list.add(arg);
            }
        }
        else
        {
            list = (List<Object>) arg;
        }

        return list;
    }

    public List<String> getList(String name)
    {
        ArrayList<String> list = new ArrayList<>();
        for (Object o : getObjectList(name))
        {
            try
            {
                list.add((String) o);
            }
            catch (ClassCastException e)
            {
                throw new IllegalArgumentException("option not String: " + name);
            }
        }
        return list;
    }

    @SuppressWarnings("unchecked")
    private void addArg(String name, Object value)
    {
        List<Object> list;
        Object arg = optArg.get(name);

        if (arg instanceof String)
        { // default value
            list = new ArrayList<>();
            optArg.put(name, list);
        }
        else
        {
            list = (List<Object>) arg;
        }

        list.add(value);
    }

    public String get(String name)
    {
        try
        {
            return (String) getObject(name);
        }
        catch (ClassCastException e)
        {
            throw new IllegalArgumentException("option not String: " + name);
        }
    }

    public int getNumber(String name)
    {
        String number = get(name);
        try
        {
            if (number != null)
            {
                return Integer.parseInt(number);
            }
            return 0;
        }
        catch (NumberFormatException e)
        {
            throw new IllegalArgumentException("option '" + name + "' not Number: " + number);
        }
    }

    public List<Object> argObjects()
    {
        return xargs;
    }

    public List<String> args()
    {
        if (args == null)
        {
            args = new ArrayList<>();
            for (Object arg : xargs)
            {
                args.add(arg == null ? "null" : arg.toString());
            }
        }
        return args;
    }

    public void usage()
    {
        StringBuilder buf = new StringBuilder();
        int index = 0;

        if (error != null)
        {
            buf.append(error);
            buf.append(NL);
            index = usageIndex;
        }

        for (int i = index; i < spec.length; ++i)
        {
            buf.append(spec[i]);
            buf.append(NL);
        }

        String msg = buf.toString();

        if (errStream != null)
        {
            errStream.print(msg);
        }
    }

    /**
     * prints usage message and returns IllegalArgumentException, for you to throw.
     */
    public IllegalArgumentException usageError(String s)
    {
        error = usageName + ": " + s;
        usage();
        return new IllegalArgumentException(error);
    }

    // internal constructor
    private Options(String[] spec, String[] gspec, Option opt)
    {
        this.gspec = gspec;
        Options gopt = (Options) opt;

        if (gspec == null && gopt == null)
        {
            this.spec = spec;
        }
        else
        {
            ArrayList<String> list = new ArrayList<>();
            list.addAll(Arrays.asList(spec));
            list.addAll(Arrays.asList(gspec != null ? gspec : gopt.gspec));
            this.spec = list.toArray(new String[0]);
        }

        Map<String, Boolean> myOptSet = new HashMap<>();
        Map<String, Object> myOptArg = new HashMap<>();

        parseSpec(myOptSet, myOptArg);

        if (gopt != null)
        {
            for (Entry<String, Boolean> e : gopt.optSet.entrySet())
            {
                if (e.getValue())
                {
                    myOptSet.put(e.getKey(), true);
                }
            }

            for (Entry<String, Object> e : gopt.optArg.entrySet())
            {
                if (!"".equals(e.getValue()))
                {
                    myOptArg.put(e.getKey(), e.getValue());
                }
            }

            gopt.reset();
        }

        unmodifiableOptSet = Collections.unmodifiableMap(myOptSet);
        unmodifiableOptArg = Collections.unmodifiableMap(myOptArg);

        defOpts = System.getenv(usageName.toUpperCase() + "_OPTS");
        defArgs = (defOpts != null) ? defOpts.split("\\s+") : new String[0];
    }

    /**
     * parse option spec.
     */
    private void parseSpec(Map<String, Boolean> myOptSet, Map<String, Object> myOptArg)
    {
        int index = 0;
        for (String line : spec)
        {
            Matcher m = parser.matcher(line);

            if (m.matches())
            {
                final String opt = m.group(GROUP_LONG_OPT_1);
                final String name = (opt != null) ? opt : m.group(GROUP_SHORT_OPT_1);

                if (name != null)
                {
                    if (myOptSet.containsKey(name))
                    {
                        throw new IllegalArgumentException("duplicate option in spec: --" + name);
                    }
                    myOptSet.put(name, false);
                }

                String dflt = (m.group(GROUP_DEFAULT) != null) ? m.group(GROUP_DEFAULT) : "";
                if (m.group(GROUP_ARG_1) != null)
                    myOptArg.put(opt, dflt);

                String opt2 = m.group(GROUP_LONG_OPT_2);
                if (opt2 != null)
                {
                    optAlias.put(opt2, opt);
                    myOptSet.put(opt2, false);
                    if (m.group(GROUP_ARG_1) != null)
                    {
                        myOptArg.put(opt2, "");
                    }
                }

                for (int i = 0; i < 2; ++i)
                {
                    String sopt = m.group(i == 0 ? GROUP_SHORT_OPT_1 : GROUP_SHORT_OPT_2);
                    if (sopt != null)
                    {
                        if (optName.containsKey(sopt))
                        {
                            throw new IllegalArgumentException("duplicate option in spec: -" + sopt);
                        }
                        optName.put(sopt, name);
                    }
                }
            }

            if (usageName == UNKNOWN)
            {
                Matcher u = uname.matcher(line);
                if (u.find())
                {
                    usageName = u.group(1);
                    usageIndex = index;
                }
            }

            index++;
        }
    }

    private void reset()
    {
        optSet.clear();
        optSet.putAll(unmodifiableOptSet);
        optArg.clear();
        optArg.putAll(unmodifiableOptArg);
        xargs.clear();
        args = null;
        error = null;
    }

    public Option parse(Object[] argv)
    {
        return parse(argv, false);
    }

    public Option parse(List<?> argv)
    {
        return parse(argv, false);
    }

    public Option parse(Object[] argv, boolean skipArg0)
    {
        if (null == argv)
        {
            throw new IllegalArgumentException("argv is null");
        }
        return parse(Arrays.asList(argv), skipArg0);
    }

    public Option parse(List<?> argv, boolean skipArg0)
    {
        reset();
        List<Object> args = new ArrayList<Object>(Arrays.asList(defArgs));
        for (Object arg : argv)
        {
            if (skipArg0)
            {
                skipArg0 = false;
                usageName = arg.toString();
            }
            else
            {
                args.add(arg);
            }
        }

        String needArg = null;
        String needOpt = null;
        boolean endOpt = false;

        for (Object oarg : args)
        {
            String arg = oarg == null ? "null" : oarg.toString();

            if (endOpt)
            {
                xargs.add(oarg);
            }
            else if (needArg != null)
            {
                addArg(needArg, oarg);
                needArg = null;
                needOpt = null;
            }
            else if (!arg.startsWith("-") || "-".equals(oarg))
            {
                if (optionsFirst)
                {
                    endOpt = true;
                }
                xargs.add(oarg);
            }
            else
            {
                if (arg.equals("--"))
                {
                    endOpt = true;
                }
                else if (arg.startsWith("--"))
                {
                    int eq = arg.indexOf("=");
                    String value = (eq == -1) ? null : arg.substring(eq + 1);
                    String name = arg.substring(2, ((eq == -1) ? arg.length() : eq));
                    List<String> names = new ArrayList<>();

                    if (optSet.containsKey(name))
                    {
                        names.add(name);
                    }
                    else
                    {
                        for (String k : optSet.keySet())
                        {
                            if (k.startsWith(name))
                                names.add(k);
                        }
                    }

                    switch (names.size())
                    {
                        case 1:
                            name = names.get(0);
                            optSet.put(name, true);
                            if (optArg.containsKey(name))
                            {
                                if (value != null)
                                    addArg(name, value);
                                else
                                    needArg = name;
                            }
                            else if (value != null)
                            {
                                throw usageError("option '--" + name + "' doesn't allow an argument");
                            }
                            break;

                        case 0:
                            if (stopOnBadOption)
                            {
                                endOpt = true;
                                xargs.add(oarg);
                                break;
                            }
                            else
                                throw usageError("invalid option '--" + name + "'");

                        default:
                            throw usageError("option '--" + name + "' is ambiguous: " + names);
                    }
                }
                else
                {
                    for (int i = 1; i < arg.length(); i++)
                    {
                        String c = String.valueOf(arg.charAt(i));
                        if (optName.containsKey(c))
                        {
                            String name = optName.get(c);
                            optSet.put(name, true);
                            if (optArg.containsKey(name))
                            {
                                int k = i + 1;
                                if (k < arg.length())
                                {
                                    addArg(name, arg.substring(k));
                                }
                                else
                                {
                                    needOpt = c;
                                    needArg = name;
                                }
                                break;
                            }
                        }
                        else
                        {
                            if (stopOnBadOption)
                            {
                                xargs.add("-" + c);
                                endOpt = true;
                            }
                            else
                                throw usageError("invalid option '" + c + "'");
                        }
                    }
                }
            }
        }

        if (needArg != null)
        {
            String name = (needOpt != null) ? needOpt : "--" + needArg;
            throw usageError("option '" + name + "' requires an argument");
        }

        // remove long option aliases
        for (Entry<String, String> alias : optAlias.entrySet())
        {
            if (optSet.get(alias.getKey()))
            {
                optSet.put(alias.getValue(), true);
                if (optArg.containsKey(alias.getKey()))
                    optArg.put(alias.getValue(), optArg.get(alias.getKey()));
            }
            optSet.remove(alias.getKey());
            optArg.remove(alias.getKey());
        }

        return this;
    }

    @Override
    public String toString()
    {
        return "isSet" + optSet + "\nArg" + optArg + "\nargs" + xargs;
    }

}
