/*
 * 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.time.Duration;
import java.util.Collection;
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) 0},
        { char.class, Character.class, (char) 0},
        { double.class, Double.class, 0D},
        { float.class, Float.class, 0F},
        { int.class, Integer.class, 0},
        { long.class, Long.class, 0L},
        { short.class, Short.class, (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 (Map.Entry<Object, Object> objectObjectEntry : defaults.entrySet()) {
                entry = (Map.Entry) objectObjectEntry;
                if (!containsKey(entry.getKey()))
                    setInto(obj, entry);
            }
        }

        // set from main map
        Options invalidEntries = null;
        Map.Entry e;
        for (Map.Entry<Object, Object> objectObjectEntry : entrySet()) {
            e = (Map.Entry) objectObjectEntry;
            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 (Method meth : meths) {
            if (meth.getName().startsWith("set")) {
                params = meth.getParameterTypes();
                if (params.length == 0)
                    continue;
                if (params[0].isArray())
                    continue;

                names.add(StringUtil.capitalize(
                        meth.getName().substring(3)));
            }
        }

        // check for public fields
        Field[] fields = type.getFields();
        for (Field field : fields) {
            names.add(StringUtil.capitalize(field.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 (Method meth : meths) {
            if (meth.getName().equals(set)) {
                params = meth.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 = meth;
                else if (params.length < setMeth.getParameterTypes().length)
                    setMeth = meth;
                else if (params.length == setMeth.getParameterTypes().length
                        && params[0] == String.class)
                    setMeth = meth;
            }
            else if (meth.getName().equals(get))
                getMeth = meth;
        }

        // 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 (Field field : fields) {
                if (field.getName().equals(base)
                        || field.getName().equals(uncapBase)) {
                    setter = field;
                    getter = field;
                    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 (Object[] primWrapper : _primWrappers)
                if (type == primWrapper[0])
                    return stringToObject(str, (Class<?>) primWrapper[1]);

        // special case for Durations
        if (type == Duration.class) {
            return Duration.ofMillis(Long.valueOf(str));
        }

        // 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 (Object[] primWrapper : _primWrappers)
            if (primWrapper[0] == type)
                return primWrapper[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();
        }
    }
}
