/*
 * Copyright (C) 2010 The Android Open Source Project
 *
 * Licensed 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 vogar;

import com.google.common.collect.Lists;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import vogar.util.Strings;

/**
 * Parses command line options.
 *
 * Strings in the passed-in String[] are parsed left-to-right. Each
 * String is classified as a short option (such as "-v"), a long
 * option (such as "--verbose"), an argument to an option (such as
 * "out.txt" in "-f out.txt"), or a non-option positional argument.
 *
 * A simple short option is a "-" followed by a short option
 * character. If the option requires an argument (which is true of any
 * non-boolean option), it may be written as a separate parameter, but
 * need not be. That is, "-f out.txt" and "-fout.txt" are both
 * acceptable.
 *
 * It is possible to specify multiple short options after a single "-"
 * as long as all (except possibly the last) do not require arguments.
 *
 * A long option begins with "--" followed by several characters. If
 * the option requires an argument, it may be written directly after
 * the option name, separated by "=", or as the next argument. (That
 * is, "--file=out.txt" or "--file out.txt".)
 *
 * A boolean long option '--name' automatically gets a '--no-name'
 * companion. Given an option "--flag", then, "--flag", "--no-flag",
 * "--flag=true" and "--flag=false" are all valid, though neither
 * "--flag true" nor "--flag false" are allowed (since "--flag" by
 * itself is sufficient, the following "true" or "false" is
 * interpreted separately). You can use "yes" and "no" as synonyms for
 * "true" and "false".
 *
 * Each String not starting with a "-" and not a required argument of
 * a previous option is a non-option positional argument, as are all
 * successive Strings. Each String after a "--" is a non-option
 * positional argument.
 *
 * Parsing of numeric fields such byte, short, int, long, float, and
 * double fields is supported. This includes both unboxed and boxed
 * versions (e.g. int vs Integer). If there is a problem parsing the
 * argument to match the desired type, a runtime exception is thrown.
 *
 * File option fields are supported by simply wrapping the string
 * argument in a File object without testing for the existance of the
 * file.
 *
 * Parameterized Collection fields such as List<File> and Set<String>
 * are supported as long as the parameter type is otherwise supported
 * by the option parser. The collection field should be initialized
 * with an appropriate collection instance.
 *
 * Enum types are supported. Input may be in either CONSTANT_CASE or
 * lower_case.
 *
 * The fields corresponding to options are updated as their options
 * are processed. Any remaining positional arguments are returned as a
 * List<String>.
 *
 * Here's a simple example:
 *
 * // This doesn't need to be a separate class, if your application doesn't warrant it.
 * // Non-@Option fields will be ignored.
 * class Options {
 *     @Option(names = { "-q", "--quiet" })
 *     boolean quiet = false;
 *
 *     // Boolean options require a long name if it's to be possible to explicitly turn them off.
 *     // Here the user can use --no-color.
 *     @Option(names = { "--color" })
 *     boolean color = true;
 *
 *     @Option(names = { "-m", "--mode" })
 *     String mode = "standard; // Supply a default just by setting the field.
 *
 *     @Option(names = { "-p", "--port" })
 *     int portNumber = 8888;
 *
 *     // There's no need to offer a short name for rarely-used options.
 *     @Option(names = { "--timeout" })
 *     double timeout = 1.0;
 *
 *     @Option(names = { "-o", "--output-file" })
 *     File output;
 *
 *     // Multiple options are added to the collection.
 *     // The collection field itself must be non-null.
 *     @Option(names = { "-i", "--input-file" })
 *     List<File> inputs = new ArrayList<File>();
 *
 * }
 *
 * class Main {
 *     public static void main(String[] args) {
 *         Options options = new Options();
 *         List<String> inputFilenames = new OptionParser(options).parse(args);
 *         for (String inputFilename : inputFilenames) {
 *             if (!options.quiet) {
 *                 ...
 *             }
 *             ...
 *         }
 *     }
 * }
 *
 * See also:
 *
 *  the getopt(1) man page
 *  Python's "optparse" module (http://docs.python.org/library/optparse.html)
 *  the POSIX "Utility Syntax Guidelines" (http://www.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap12.html#tag_12_02)
 *  the GNU "Standards for Command Line Interfaces" (http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Interfaces)
 */
public class OptionParser {
    private static final HashMap<Class<?>, Handler> handlers = new HashMap<Class<?>, Handler>();
    static {
        handlers.put(boolean.class, new BooleanHandler());
        handlers.put(Boolean.class, new BooleanHandler());

        handlers.put(byte.class, new ByteHandler());
        handlers.put(Byte.class, new ByteHandler());
        handlers.put(short.class, new ShortHandler());
        handlers.put(Short.class, new ShortHandler());
        handlers.put(int.class, new IntegerHandler());
        handlers.put(Integer.class, new IntegerHandler());
        handlers.put(long.class, new LongHandler());
        handlers.put(Long.class, new LongHandler());

        handlers.put(float.class, new FloatHandler());
        handlers.put(Float.class, new FloatHandler());
        handlers.put(double.class, new DoubleHandler());
        handlers.put(Double.class, new DoubleHandler());

        handlers.put(String.class, new StringHandler());
        handlers.put(File.class, new FileHandler());
    }
    Handler getHandler(Type type) {
        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;
            Class rawClass = (Class<?>) parameterizedType.getRawType();
            if (!Collection.class.isAssignableFrom(rawClass)) {
                throw new RuntimeException("cannot handle non-collection parameterized type " + type);
            }
            Type actualType = parameterizedType.getActualTypeArguments()[0];
            if (!(actualType instanceof Class)) {
                throw new RuntimeException("cannot handle nested parameterized type " + type);
            }
            return getHandler(actualType);
        }
        if (type instanceof Class) {
            Class<?> classType = (Class) type;
            if (Collection.class.isAssignableFrom(classType)) {
                // could handle by just having a default of treating
                // contents as String but consciously decided this
                // should be an error
                throw new RuntimeException(
                        "cannot handle non-parameterized collection " + type + ". " +
                        "use a generic Collection to specify a desired element type");
            }
            if (classType.isEnum()) {
                return new EnumHandler(classType);
            }
            return handlers.get(classType);
        }
        throw new RuntimeException("cannot handle unknown field type " + type);
    }

    private final Object optionSource;
    private final HashMap<String, Field> optionMap;
    private final Map<Field, Object> defaultOptionMap;

    /**
     * Constructs a new OptionParser for setting the @Option fields of 'optionSource'.
     */
    public OptionParser(Object optionSource) {
        this.optionSource = optionSource;
        this.optionMap = makeOptionMap();
        this.defaultOptionMap = new HashMap<Field, Object>();
    }

    public static String[] readFile(File configFile) {
        if (!configFile.exists()) {
            return new String[0];
        }

        List<String> configFileLines;
        try {
            configFileLines = Strings.readFileLines(configFile);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        List<String> argsList = Lists.newArrayList();
        for (String rawLine : configFileLines) {
            String line = rawLine.trim();

            // allow comments and blank lines
            if (line.startsWith("#") || line.isEmpty()) {
                continue;
            }
            int space = line.indexOf(' ');
            if (space == -1) {
                argsList.add(line);
            } else {
                argsList.add(line.substring(0, space));
                argsList.add(line.substring(space + 1).trim());
            }
        }

        return argsList.toArray(new String[argsList.size()]);
    }

    /**
     * Parses the command-line arguments 'args', setting the @Option fields of the 'optionSource' provided to the constructor.
     * Returns a list of the positional arguments left over after processing all options.
     */
    public List<String> parse(String[] args) {
        return parseOptions(Arrays.asList(args).iterator());
    }

    private List<String> parseOptions(Iterator<String> args) {
        final List<String> leftovers = new ArrayList<String>();

        // Scan 'args'.
        while (args.hasNext()) {
            final String arg = args.next();
            if (arg.equals("--")) {
                // "--" marks the end of options and the beginning of positional arguments.
                break;
            } else if (arg.startsWith("--")) {
                // A long option.
                parseLongOption(arg, args);
            } else if (arg.startsWith("-")) {
                // A short option.
                parseGroupedShortOptions(arg, args);
            } else {
                // The first non-option marks the end of options.
                leftovers.add(arg);
                break;
            }
        }

        // Package up the leftovers.
        while (args.hasNext()) {
            leftovers.add(args.next());
        }
        return leftovers;
    }

    private Field fieldForArg(String name) {
        final Field field = optionMap.get(name);
        if (field == null) {
            throw new RuntimeException("unrecognized option '" + name + "'");
        }
        return field;
    }

    private void parseLongOption(String arg, Iterator<String> args) {
        String name = arg.replaceFirst("^--no-", "--");
        String value = null;

        // Support "--name=value" as well as "--name value".
        final int equalsIndex = name.indexOf('=');
        if (equalsIndex != -1) {
            value = name.substring(equalsIndex + 1);
            name = name.substring(0, equalsIndex);
        }

        final Field field = fieldForArg(name);
        final Handler handler = getHandler(field.getGenericType());
        if (value == null) {
            if (handler.isBoolean()) {
                value = arg.startsWith("--no-") ? "false" : "true";
            } else {
                value = grabNextValue(args, name, field);
            }
        }
        setValue(field, arg, handler, value);
    }

    // Given boolean options a and b, and non-boolean option f, we want to allow:
    // -ab
    // -abf out.txt
    // -abfout.txt
    // (But not -abf=out.txt --- POSIX doesn't mention that either way, but GNU expressly forbids it.)
    private void parseGroupedShortOptions(String arg, Iterator<String> args) {
        for (int i = 1; i < arg.length(); ++i) {
            final String name = "-" + arg.charAt(i);
            final Field field = fieldForArg(name);
            final Handler handler = getHandler(field.getGenericType());
            String value;
            if (handler.isBoolean()) {
                value = "true";
            } else {
                // We need a value. If there's anything left, we take the rest of this "short option".
                if (i + 1 < arg.length()) {
                    value = arg.substring(i + 1);
                    i = arg.length() - 1;
                } else {
                    value = grabNextValue(args, name, field);
                }
            }
            setValue(field, arg, handler, value);
        }
    }

    @SuppressWarnings("unchecked")
    private void setValue(Field field, String arg, Handler handler, String valueText) {

        Object value = handler.translate(valueText);
        if (value == null) {
            final String type = field.getType().getSimpleName().toLowerCase();
            throw new RuntimeException("couldn't convert '" + valueText + "' to a " + type + " for option '" + arg + "'");
        }
        try {
            field.setAccessible(true);
            // record the original value of the field so it can be reset
            if (!defaultOptionMap.containsKey(field)) {
                defaultOptionMap.put(field, field.get(optionSource));
            }
            if (Collection.class.isAssignableFrom(field.getType())) {
                Collection collection = (Collection) field.get(optionSource);
                collection.add(value);
            } else {
                field.set(optionSource, value);
            }
        } catch (IllegalAccessException ex) {
            throw new RuntimeException("internal error", ex);
        }
    }

    /**
     * Resets optionSource's fields to their defaults
     */
    public void reset() {
        for (Map.Entry<Field, Object> entry : defaultOptionMap.entrySet()) {
            try {
                entry.getKey().set(optionSource, entry.getValue());
            } catch (IllegalAccessException e) {
                throw new RuntimeException(e);
            }
        }
    }

    // Returns the next element of 'args' if there is one. Uses 'name' and 'field' to construct a helpful error message.
    private String grabNextValue(Iterator<String> args, String name, Field field) {
        if (!args.hasNext()) {
            final String type = field.getType().getSimpleName().toLowerCase();
            throw new RuntimeException("option '" + name + "' requires a " + type + " argument");
        }
        return args.next();
    }

    // Cache the available options and report any problems with the options themselves right away.
    private HashMap<String, Field> makeOptionMap() {
        final HashMap<String, Field> optionMap = new HashMap<String, Field>();
        final Class<?> optionClass = optionSource.getClass();
        for (Field field : optionClass.getDeclaredFields()) {
            if (field.isAnnotationPresent(Option.class)) {
                final Option option = field.getAnnotation(Option.class);
                final String[] names = option.names();
                if (names.length == 0) {
                    throw new RuntimeException("found an @Option with no name!");
                }
                for (String name : names) {
                    if (optionMap.put(name, field) != null) {
                        throw new RuntimeException("found multiple @Options sharing the name '" + name + "'");
                    }
                }
                if (getHandler(field.getGenericType()) == null) {
                    throw new RuntimeException("unsupported @Option field type '" + field.getType() + "'");
                }
            }
        }
        return optionMap;
    }

    static abstract class Handler {
        // Only BooleanHandler should ever override this.
        boolean isBoolean() {
            return false;
        }

        /**
         * Returns an object of appropriate type for the given Handle, corresponding to 'valueText'.
         * Returns null on failure.
         */
        abstract Object translate(String valueText);
    }

    static class BooleanHandler extends Handler {
        @Override boolean isBoolean() {
            return true;
        }

        Object translate(String valueText) {
            if (valueText.equalsIgnoreCase("true") || valueText.equalsIgnoreCase("yes")) {
                return Boolean.TRUE;
            } else if (valueText.equalsIgnoreCase("false") || valueText.equalsIgnoreCase("no")) {
                return Boolean.FALSE;
            }
            return null;
        }
    }

    static class ByteHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Byte.parseByte(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class ShortHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Short.parseShort(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class IntegerHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Integer.parseInt(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class LongHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Long.parseLong(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class FloatHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Float.parseFloat(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class DoubleHandler extends Handler {
        Object translate(String valueText) {
            try {
                return Double.parseDouble(valueText);
            } catch (NumberFormatException ex) {
                return null;
            }
        }
    }

    static class StringHandler extends Handler {
        Object translate(String valueText) {
            return valueText;
        }
    }

    @SuppressWarnings("unchecked") // creating an instance with a non-enum type is an error!
    static class EnumHandler extends Handler {
        private final Class<?> enumType;

        public EnumHandler(Class<?> enumType) {
            this.enumType = enumType;
        }

        Object translate(String valueText) {
            try {
                return Enum.valueOf((Class) enumType, valueText.toUpperCase());
            } catch (IllegalArgumentException e) {
                return null;
            }
        }
    }

    static class FileHandler extends Handler {
        Object translate(String valueText) {
            return new File(valueText).getAbsoluteFile();
        }
    }
}
