/*
 * 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.openjpa.lib.util;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.Member;
import java.lang.reflect.Method;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.TreeSet;


/**
 * A specialization of the {@link Properties} map type with the added
 * abilities to read application options from the command line and to
 * use bean patterns to set an object's properties via command-line the
 * stored mappings.
 * A typical use pattern for this class is to construct a new instance
 * in the <code>main</code> method, then call {@link #setFromCmdLine} with the
 * given args. Next, an instanceof the class being invoked is created, and
 * {@link #setInto} is called with that instance as a parameter. With this
 * pattern, the user can configure any bean properties of the class, or even
 * properties of classes reachable from the class, through the command line.
 *
 * @author Abe White
 */
public class Options extends TypedProperties {
    private static final long serialVersionUID = 1L;

    /**
     * Immutable empty instance.
     */
    public static Options EMPTY = new EmptyOptions();

    // maps primitive types to the appropriate wrapper class and default value
    private static Object[][] _primWrappers = new Object[][]{
        { boolean.class, Boolean.class, Boolean.FALSE },
        { byte.class, Byte.class, Byte.valueOf((byte) 0) },
        { char.class, Character.class, Character.valueOf((char) 0) },
        { double.class, Double.class, Double.valueOf(0D) },
        { float.class, Float.class, Float.valueOf(0F) },
        { int.class, Integer.class, Integer.valueOf(0) },
        { long.class, Long.class, Long.valueOf(0L) },
        { short.class, Short.class, Short.valueOf((short) 0) }, };

    private static Localizer _loc = Localizer.forPackage(Options.class);

    /**
     * Default constructor.
     */
    public Options() {
        super();
    }

    /**
     * Construct the options instance with the given set of defaults.
     *
     * @see Properties#Properties(Properties)
     */
    public Options(Properties defaults) {
        super(defaults);
    }

    /**
     * Parses the given argument list into flag/value pairs, which are stored
     * as properties. Flags that are present without values are given
     * the value "true". If any flag is found for which there is already
     * a mapping present, the existing mapping will be overwritten.
     * Flags should be of the form:<br />
     * <code>java Foo -flag1 value1 -flag2 value2 ... arg1 arg2 ...</code>
     *
     * @param args the command-line arguments
     * @return all arguments in the original array beyond the
     * flag/value pair list
     * @author Patrick Linskey
     */
    public String[] setFromCmdLine(String[] args) {
        if (args == null || args.length == 0)
            return args;

        String key = null;
        String value = null;
        List<String> remainder = new LinkedList<>();
        for (int i = 0; i < args.length + 1; i++) {
            if (i == args.length || args[i].startsWith("-")) {
                key = trimQuote(key);
                if (key != null) {
                    if (!StringUtil.isEmpty(value))
                        setProperty(key, trimQuote(value));
                    else
                        setProperty(key, "true");
                }

                if (i == args.length)
                    break;
                else {
                    key = args[i].substring(1);
                    value = null;
                }
            } else if (key != null) {
                setProperty(key, trimQuote(args[i]));
                key = null;
            } else
                remainder.add(args[i]);
        }

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

    /**
     * This method uses reflection to set all the properties in the given
     * object that are named by the keys in this map. For a given key 'foo',
     * the algorithm will look for a 'setFoo' method in the given instance.
     * For a given key 'foo.bar', the algorithm will first look for a
     * 'getFoo' method in the given instance, then will recurse on the return
     * value of that method, now looking for the 'bar' property. This allows
     * the setting of nested object properties. If in the above example the
     * 'getFoo' method is not present or returns null, the algorithm will
     * look for a 'setFoo' method; if found it will constrct a new instance
     * of the correct type, set it using the 'setFoo' method, then recurse on
     * it as above. Property names can be nested in this way to an arbitrary
     * depth. For setter methods that take multiple parameters, the value
     * mapped to the key can use the ',' as an argument separator character.
     * If not enough values are present for a given method after splitting
     * the string on ',', the remaining arguments will receive default
     * values. All arguments are converted from string form to the
     * correct type if possible(i.e. if the type is primitive,
     * java.lang.Clas, or has a constructor that takes a single string
     * argument). Examples:
     * <ul>
     * <li>Map Entry: <code>"age"-&gt;"12"</code><br />
     * Resultant method call: <code>obj.setAge(12)</code></li>
     * <li>Map Entry: <code>"range"-&gt;"1,20"</code><br />
     * Resultant method call: <code>obj.setRange(1, 20)</code></li>
     * <li>Map Entry: <code>"range"-&gt;"10"</code><br />
     * Resultant method call: <code>obj.setRange(10, 10)</code></li>
     * <li>Map Entry: <code>"brother.name"-&gt;"Bob"</code><br />
     * Resultant method call: <code>obj.getBrother().setName("Bob")
     * <code></li>
     * </ul>
     * Any keys present in the map for which there is no
     * corresponding property in the given object will be ignored,
     * and will be returned in the {@link Map} returned by this method.
     *
     * @return an {@link Options} of key-value pairs in this object
     * for which no setters could be found.
     * @throws RuntimeException on parse error
     */
    public Options setInto(Object obj) {
        // set all defaults that have no explicit value
        Map.Entry entry = null;
        if (defaults != null) {
            for (Iterator<?> itr = defaults.entrySet().iterator(); itr.hasNext();) {
                entry = (Map.Entry) itr.next();
                if (!containsKey(entry.getKey()))
                    setInto(obj, entry);
            }
        }

        // set from main map
        Options invalidEntries = null;
        Map.Entry e;
        for (Iterator<?> itr = entrySet().iterator(); itr.hasNext();) {
            e = (Map.Entry) itr.next();
            if (!setInto(obj, e)) {
                if (invalidEntries == null)
                    invalidEntries = new Options();
                invalidEntries.put(e.getKey(), e.getValue());
            }
        }
        return (invalidEntries == null) ? EMPTY : invalidEntries;
    }

    /**
     * Sets the property named by the key of the given entry in the
     * given object.
     *
     * @return <code>true</code> if the set succeeded, or
     * <code>false</code> if no method could be found for this property.
     */
    private boolean setInto(Object obj, Map.Entry entry) {
        if (entry.getKey() == null)
            return false;

        try {
            // look for matching parameter of object
            Object[] match = new Object[]{ obj, null };
            if (!matchOptionToMember(entry.getKey().toString(), match))
                return false;

            Class[] type = getType(match[1]);
            Object[] values = new Object[type.length];
            String[] strValues;
            if (entry.getValue() == null)
                strValues = new String[1];
            else if (values.length == 1)
                strValues = new String[]{ entry.getValue().toString() };
            else
                strValues = StringUtil.split(entry.getValue().toString(), ",", 0);

            // convert the string values into parameter values, if not
            // enough string values repeat last one for rest
            for (int i = 0; i < strValues.length; i++)
                values[i] = stringToObject(strValues[i].trim(), type[i]);
            for (int i = strValues.length; i < values.length; i++)
                values[i] = getDefaultValue(type[i]);

            // invoke the setter / set the field
            invoke(match[0], match[1], values);
            return true;
        } catch (Throwable t) {
            throw new ParseException(obj + "." + entry.getKey() + " = " + entry.getValue(), t);
        }
    }

    /**
     * Removes leading and trailing single quotes from the given String, if any.
     */
    private static String trimQuote(String val) {
        if (val != null && val.startsWith("'") && val.endsWith("'"))
            return val.substring(1, val.length() - 1);
        return val;
    }

    /**
     * Finds all the options that can be set on the provided class. This does
     * not look for path-traversal expressions.
     *
     * @param type The class for which available options should be listed.
     * @return The available option names in <code>type</code>. The
     * names will have initial caps. They will be ordered alphabetically.
     */
    public static Collection<String> findOptionsFor(Class<?> type) {
        Collection<String> names = new TreeSet<>();
        // look for a setter method matching the key
        Method[] meths = type.getMethods();
        Class<?>[] params;
        for (int i = 0; i < meths.length; i++) {
            if (meths[i].getName().startsWith("set")) {
                params = meths[i].getParameterTypes();
                if (params.length == 0)
                    continue;
                if (params[0].isArray())
                    continue;

                names.add(StringUtil.capitalize(
                    meths[i].getName().substring(3)));
            }
        }

        // check for public fields
        Field[] fields = type.getFields();
        for (int i = 0; i < fields.length; i++)
            names.add(StringUtil.capitalize(fields[i].getName()));

        return names;
    }

    /**
     * Matches a key to an object/setter pair.
     *
     * @param key the key given at the command line; may be of the form
     * 'foo.bar' to signify the 'bar' property of the 'foo' owned object
     * @param match an array of length 2, where the first index is set
     * to the object to retrieve the setter for
     * @return true if a match was made, false otherwise; additionally,
     * the first index of the match array will be set to
     * the matching object and the second index will be
     * set to the setter method or public field for the
     * property named by the key
     */
    private static boolean matchOptionToMember(String key, Object[] match)
        throws Exception {
        if (StringUtil.isEmpty(key))
            return false;

        // unfortunately we can't use bean properties for setters; any
        // setter with more than 1 argument is ignored; calculate setter and getter
        // name to look for
        String[] find = StringUtil.split(key, ".", 2);
        String base = StringUtil.capitalize(find[0]);
        String set = "set" + base;
        String get = "get" + base;

        // look for a setter/getter matching the key; look for methods first
        Class<?> type = match[0].getClass();
        Method[] meths = type.getMethods();
        Method setMeth = null;
        Method getMeth = null;
        Class[] params;
        for (int i = 0; i < meths.length; i++) {
            if (meths[i].getName().equals(set)) {
                params = meths[i].getParameterTypes();
                if (params.length == 0)
                    continue;
                if (params[0].isArray())
                    continue;

                // use this method if we haven't found any other setter, if
                // it has less parameters than any other setter, or if it uses
                // string parameters
                if (setMeth == null)
                    setMeth = meths[i];
                else if (params.length < setMeth.getParameterTypes().length)
                    setMeth = meths[i];
                else if (params.length == setMeth.getParameterTypes().length
                    && params[0] == String.class)
                    setMeth = meths[i];
            } else if (meths[i].getName().equals(get))
                getMeth = meths[i];
        }

        // if no methods found, check for public field
        Member setter = setMeth;
        Member getter = getMeth;
        if (setter == null) {
            Field[] fields = type.getFields();
            String uncapBase = StringUtil.uncapitalize(find[0]);
            for (int i = 0; i < fields.length; i++) {
                if (fields[i].getName().equals(base)
                    || fields[i].getName().equals(uncapBase)) {
                    setter = fields[i];
                    getter = fields[i];
                    break;
                }
            }
        }

        // if no way to access property, give up
        if (setter == null && getter == null)
            return false;

        // recurse on inner object with remainder of key?
        if (find.length > 1) {
            Object inner = null;
            if (getter != null)
                inner = invoke(match[0], getter, null);

            // if no getter or current inner is null, try to create a new
            // inner instance and set it in object
            if (inner == null && setter != null) {
                Class<?> innerType = getType(setter)[0];
                try {
                    inner = AccessController.doPrivileged(
                        J2DoPrivHelper.newInstanceAction(innerType));
                } catch (PrivilegedActionException pae) {
                    throw pae.getException();
                }
                invoke(match[0], setter, new Object[]{ inner });
            }
            match[0] = inner;
            return matchOptionToMember(find[1], match);
        }

        // got match; find setter for property
        match[1] = setter;
        return match[1] != null;
    }

    /**
     * Return the types of the parameters needed to set the given member.
     */
    private static Class<?>[] getType(Object member) {
        if (member instanceof Method)
            return ((Method) member).getParameterTypes();
        return new Class[]{ ((Field) member).getType() };
    }

    /**
     * Set the given member to the given value(s).
     */
    private static Object invoke(Object target, Object member, Object[] values)
        throws Exception {
        if (member instanceof Method)
            return ((Method) member).invoke(target, values);
        if (values == null || values.length == 0)
            return ((Field) member).get(target);
        ((Field) member).set(target, values[0]);
        return null;
    }

    /**
     * Converts the given string into an object of the given type, or its
     * wrapper type if it is primitive.
     */
    private Object stringToObject(String str, Class<?> type) throws Exception {
        // special case for null and for strings
        if (str == null || type == String.class)
            return str;

        // special case for creating Class instances
        if (type == Class.class)
            return Class.forName(str, false, getClass().getClassLoader());

        // special case for numeric types that end in .0; strip the decimal
        // places because it can kill int, short, long parsing
        if (type.isPrimitive() || Number.class.isAssignableFrom(type))
            if (str.length() > 2 && str.endsWith(".0"))
                str = str.substring(0, str.length() - 2);

        // for primitives, recurse on wrapper type
        if (type.isPrimitive())
            for (int i = 0; i < _primWrappers.length; i++)
                if (type == _primWrappers[i][0])
                    return stringToObject(str, (Class<?>) _primWrappers[i][1]);

        // look for a string constructor
        Exception err = null;
        try {
            Constructor<?> cons = type.getConstructor(new Class[]{ String.class });
            if (type == Boolean.class && "t".equalsIgnoreCase(str))
                str = "true";
            return cons.newInstance(new Object[]{ str });
        } catch (Exception e) {
            err = new ParseException(_loc.get("conf-no-constructor", str, type), e);
        }

        // special case: the argument value is a subtype name and a new instance
        // of that type should be set as the object
        Class<?> subType = null;
        try {
            subType = Class.forName(str);
        } catch (Exception e) {
            err = e;
            throw new ParseException(_loc.get("conf-no-type", str, type), e);
        }
        if (!type.isAssignableFrom(subType))
            throw err;
        try {
            return AccessController.doPrivileged(J2DoPrivHelper.newInstanceAction(subType));
        } catch (PrivilegedActionException pae) {
            throw pae.getException();
        }
    }

    /**
     * Returns the default value for the given parameter type.
     */
    private Object getDefaultValue(Class<?> type) {
        for (int i = 0; i < _primWrappers.length; i++)
            if (_primWrappers[i][0] == type)
                return _primWrappers[i][2];

        return null;
    }

    /**
     * Specialization of {@link #getBooleanProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public boolean getBooleanProperty(String key, String key2, boolean def) {
        String val = getProperty(key);
        if (val == null)
            val = getProperty(key2);
        if (val == null)
            return def;
        return "t".equalsIgnoreCase(val) || "true".equalsIgnoreCase(val);
    }

    /**
     * Specialization of {@link TypedProperties#getFloatProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public float getFloatProperty(String key, String key2, float def) {
        String val = getProperty(key);
        if (val == null)
            val = getProperty(key2);
        return (val == null) ? def : Float.parseFloat(val);
    }

    /**
     * Specialization of {@link TypedProperties#getDoubleProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public double getDoubleProperty(String key, String key2, double def) {
        String val = getProperty(key);
        if (val == null)
            val = getProperty(key2);
        return (val == null) ? def : Double.parseDouble(val);
    }

    /**
     * Specialization of {@link TypedProperties#getLongProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public long getLongProperty(String key, String key2, long def) {
        String val = getProperty(key);
        if (val == null)
            val = getProperty(key2);
        return (val == null) ? def : Long.parseLong(val);
    }

    /**
     * Specialization of {@link TypedProperties#getIntProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public int getIntProperty(String key, String key2, int def) {
        String val = getProperty(key);
        if (val == null)
            val = getProperty(key2);
        return (val == null) ? def : Integer.parseInt(val);
    }

    /**
     * Specialization of {@link Properties#getProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public String getProperty(String key, String key2, String def) {
        String val = getProperty(key);
        return (val == null) ? getProperty(key2, def) : val;
    }

    /**
     * Specialization of {@link TypedProperties#removeBooleanProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public boolean removeBooleanProperty(String key, String key2, boolean def) {
        String val = removeProperty(key);
        if (val == null)
            val = removeProperty(key2);
        else
            removeProperty(key2);
        if (val == null)
            return def;
        return "t".equalsIgnoreCase(val) || "true".equalsIgnoreCase(val);
    }

    /**
     * Specialization of {@link TypedProperties#removeFloatProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public float removeFloatProperty(String key, String key2, float def) {
        String val = removeProperty(key);
        if (val == null)
            val = removeProperty(key2);
        else
            removeProperty(key2);
        return (val == null) ? def : Float.parseFloat(val);
    }

    /**
     * Specialization of {@link TypedProperties#removeDoubleProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public double removeDoubleProperty(String key, String key2, double def) {
        String val = removeProperty(key);
        if (val == null)
            val = removeProperty(key2);
        else
            removeProperty(key2);
        return (val == null) ? def : Double.parseDouble(val);
    }

    /**
     * Specialization of {@link TypedProperties#removeLongProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public long removeLongProperty(String key, String key2, long def) {
        String val = removeProperty(key);
        if (val == null)
            val = removeProperty(key2);
        else
            removeProperty(key2);
        return (val == null) ? def : Long.parseLong(val);
    }

    /**
     * Specialization of {@link TypedProperties#removeIntProperty} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public int removeIntProperty(String key, String key2, int def) {
        String val = removeProperty(key);
        if (val == null)
            val = removeProperty(key2);
        else
            removeProperty(key2);
        return (val == null) ? def : Integer.parseInt(val);
    }

    /**
     * Specialization of {@link Properties#remove(Object)} to allow
     * a value to appear under either of two keys; useful for short and
     * long versions of command-line flags.
     */
    public String removeProperty(String key, String key2, String def) {
        String val = removeProperty(key);
        return (val == null) ? removeProperty(key2, def) : val;
    }

    /**
     * Immutable empty options.
     */
    private static class EmptyOptions extends Options {

        
        private static final long serialVersionUID = 1L;

        @Override
        public Object setProperty(String key, String value) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object put(Object key, Object value) {
            throw new UnsupportedOperationException();
        }
    }
}
