/*
 * Copyright (c) 2010, 2013, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package jdk.nashorn.internal.runtime.options;

import java.io.PrintWriter;
import java.security.AccessControlContext;
import java.security.AccessController;
import java.security.Permissions;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.PropertyPermission;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.TreeMap;
import java.util.TreeSet;
import jdk.nashorn.internal.runtime.QuotedStringTokenizer;

/**
 * Manages global runtime options.
 */
public final class Options {
    // permission to just read nashorn.* System properties
    private static AccessControlContext createPropertyReadAccCtxt() {
        final Permissions perms = new Permissions();
        perms.add(new PropertyPermission("nashorn.*", "read"));
        return new AccessControlContext(new ProtectionDomain[] { new ProtectionDomain(null, perms) });
    }

    private static final AccessControlContext READ_PROPERTY_ACC_CTXT = createPropertyReadAccCtxt();

    /** Resource tag. */
    private final String resource;

    /** Error writer. */
    private final PrintWriter err;

    /** File list. */
    private final List<String> files;

    /** Arguments list */
    private final List<String> arguments;

    /** The options map of enabled options */
    private final TreeMap<String, Option<?>> options;

    /** System property that can be used to prepend options to the explicitly specified command line. */
    private static final String NASHORN_ARGS_PREPEND_PROPERTY = "nashorn.args.prepend";

    /** System property that can be used to append options to the explicitly specified command line. */
    private static final String NASHORN_ARGS_PROPERTY = "nashorn.args";

    /**
     * Constructor
     *
     * Options will use System.err as the output stream for any errors
     *
     * @param resource resource prefix for options e.g. "nashorn"
     */
    public Options(final String resource) {
        this(resource, new PrintWriter(System.err, true));
    }

    /**
     * Constructor
     *
     * @param resource resource prefix for options e.g. "nashorn"
     * @param err      error stream for reporting parse errors
     */
    public Options(final String resource, final PrintWriter err) {
        this.resource  = resource;
        this.err       = err;
        this.files     = new ArrayList<>();
        this.arguments = new ArrayList<>();
        this.options   = new TreeMap<>();

        // set all default values
        for (final OptionTemplate t : Options.validOptions) {
            if (t.getDefaultValue() != null) {
                // populate from system properties
                final String v = getStringProperty(t.getKey(), null);
                if (v != null) {
                    set(t.getKey(), createOption(t, v));
                } else if (t.getDefaultValue() != null) {
                    set(t.getKey(), createOption(t, t.getDefaultValue()));
                 }
            }
        }
    }

    /**
     * Get the resource for this Options set, e.g. "nashorn"
     * @return the resource
     */
    public String getResource() {
        return resource;
    }

    @Override
    public String toString() {
        return options.toString();
    }

    /**
     * Convenience function for getting system properties in a safe way

     * @param name of boolean property
     * @param defValue default value of boolean property
     * @return true if set to true, default value if unset or set to false
     */
    public static boolean getBooleanProperty(final String name, final Boolean defValue) {
        name.getClass(); // null check
        if (!name.startsWith("nashorn.")) {
            throw new IllegalArgumentException(name);
        }

        return AccessController.doPrivileged(
                new PrivilegedAction<Boolean>() {
                    @Override
                    public Boolean run() {
                        try {
                            final String property = System.getProperty(name);
                            if (property == null && defValue != null) {
                                return defValue;
                            }
                            return property != null && !"false".equalsIgnoreCase(property);
                        } catch (final SecurityException e) {
                            // if no permission to read, assume false
                            return false;
                        }
                    }
                }, READ_PROPERTY_ACC_CTXT);
    }

    /**
     * Convenience function for getting system properties in a safe way

     * @param name of boolean property
     * @return true if set to true, false if unset or set to false
     */
    public static boolean getBooleanProperty(final String name) {
        return getBooleanProperty(name, null);
    }

    /**
     * Convenience function for getting system properties in a safe way
     *
     * @param name of string property
     * @param defValue the default value if unset
     * @return string property if set or default value
     */
    public static String getStringProperty(final String name, final String defValue) {
        name.getClass(); // null check
        if (! name.startsWith("nashorn.")) {
            throw new IllegalArgumentException(name);
        }

        return AccessController.doPrivileged(
                new PrivilegedAction<String>() {
                    @Override
                    public String run() {
                        try {
                            return System.getProperty(name, defValue);
                        } catch (final SecurityException e) {
                            // if no permission to read, assume the default value
                            return defValue;
                        }
                    }
                }, READ_PROPERTY_ACC_CTXT);
    }

    /**
     * Convenience function for getting system properties in a safe way
     *
     * @param name of integer property
     * @param defValue the default value if unset
     * @return integer property if set or default value
     */
    public static int getIntProperty(final String name, final int defValue) {
        name.getClass(); // null check
        if (! name.startsWith("nashorn.")) {
            throw new IllegalArgumentException(name);
        }

        return AccessController.doPrivileged(
                new PrivilegedAction<Integer>() {
                    @Override
                    public Integer run() {
                        try {
                            return Integer.getInteger(name, defValue);
                        } catch (final SecurityException e) {
                            // if no permission to read, assume the default value
                            return defValue;
                        }
                    }
                }, READ_PROPERTY_ACC_CTXT);
    }

    /**
     * Return an option given its resource key. If the key doesn't begin with
     * {@literal <resource>}.option it will be completed using the resource from this
     * instance
     *
     * @param key key for option
     * @return an option value
     */
    public Option<?> get(final String key) {
        return options.get(key(key));
    }

    /**
     * Return an option as a boolean
     *
     * @param key key for option
     * @return an option value
     */
    public boolean getBoolean(final String key) {
        final Option<?> option = get(key);
        return option != null ? (Boolean)option.getValue() : false;
    }

    /**
     * Return an option as a integer
     *
     * @param key key for option
     * @return an option value
     */
    public int getInteger(final String key) {
        final Option<?> option = get(key);
        return option != null ? (Integer)option.getValue() : 0;
    }

    /**
     * Return an option as a String
     *
     * @param key key for option
     * @return an option value
     */
    public String getString(final String key) {
        final Option<?> option = get(key);
        if (option != null) {
            final String value = (String)option.getValue();
            if(value != null) {
                return value.intern();
            }
        }
        return null;
    }

    /**
     * Set an option, overwriting an existing state if one exists
     *
     * @param key    option key
     * @param option option
     */
    public void set(final String key, final Option<?> option) {
        options.put(key(key), option);
    }

    /**
     * Set an option as a boolean value, overwriting an existing state if one exists
     *
     * @param key    option key
     * @param option option
     */
    public void set(final String key, final boolean option) {
        set(key, new Option<>(option));
    }

    /**
     * Set an option as a String value, overwriting an existing state if one exists
     *
     * @param key    option key
     * @param option option
     */
    public void set(final String key, final String option) {
        set(key, new Option<>(option));
    }

    /**
     * Return the user arguments to the program, i.e. those trailing "--" after
     * the filename
     *
     * @return a list of user arguments
     */
    public List<String> getArguments() {
        return Collections.unmodifiableList(this.arguments);
    }

    /**
     * Return the JavaScript files passed to the program
     *
     * @return a list of files
     */
    public List<String> getFiles() {
        return Collections.unmodifiableList(files);
    }

    /**
     * Return the option templates for all the valid option supported.
     *
     * @return a collection of OptionTemplate objects.
     */
    public static Collection<OptionTemplate> getValidOptions() {
        return Collections.unmodifiableCollection(validOptions);
    }

    /**
     * Make sure a key is fully qualified for table lookups
     *
     * @param shortKey key for option
     * @return fully qualified key
     */
    private String key(final String shortKey) {
        String key = shortKey;
        while (key.startsWith("-")) {
            key = key.substring(1, key.length());
        }
        key = key.replace("-", ".");
        final String keyPrefix = this.resource + ".option.";
        if (key.startsWith(keyPrefix)) {
            return key;
        }
        return keyPrefix + key;
    }

    static String getMsg(final String msgId, final String... args) {
        try {
            final String msg = Options.bundle.getString(msgId);
            if (args.length == 0) {
                return msg;
            }
            return new MessageFormat(msg).format(args);
        } catch (final MissingResourceException e) {
            throw new IllegalArgumentException(e);
        }
    }

    /**
     * Display context sensitive help
     *
     * @param e  exception that caused a parse error
     */
    public void displayHelp(final IllegalArgumentException e) {
        if (e instanceof IllegalOptionException) {
            final OptionTemplate template = ((IllegalOptionException)e).getTemplate();
            if (template.isXHelp()) {
                // display extended help information
                displayHelp(true);
            } else {
                err.println(((IllegalOptionException)e).getTemplate());
            }
            return;
        }

        if (e != null && e.getMessage() != null) {
            err.println(getMsg("option.error.invalid.option",
                    e.getMessage(),
                    helpOptionTemplate.getShortName(),
                    helpOptionTemplate.getName()));
            err.println();
            return;
        }

        displayHelp(false);
    }

    /**
     * Display full help
     *
     * @param extended show the extended help for all options, including undocumented ones
     */
    public void displayHelp(final boolean extended) {
        for (final OptionTemplate t : Options.validOptions) {
            if ((extended || !t.isUndocumented()) && t.getResource().equals(resource)) {
                err.println(t);
                err.println();
            }
        }
    }

    /**
     * Processes the arguments and stores their information. Throws
     * IllegalArgumentException on error. The message can be analyzed by the
     * displayHelp function to become more context sensitive
     *
     * @param args arguments from command line
     */
    public void process(final String[] args) {
        final LinkedList<String> argList = new LinkedList<>();
        addSystemProperties(NASHORN_ARGS_PREPEND_PROPERTY, argList);
        Collections.addAll(argList, args);
        addSystemProperties(NASHORN_ARGS_PROPERTY, argList);

        while (!argList.isEmpty()) {
            final String arg = argList.remove(0);

            // skip empty args
            if (arg.isEmpty()) {
                continue;
            }

            // user arguments to the script
            if ("--".equals(arg)) {
                arguments.addAll(argList);
                argList.clear();
                continue;
            }

            // If it doesn't start with -, it's a file. But, if it is just "-",
            // then it is a file representing standard input.
            if (!arg.startsWith("-") || arg.length() == 1) {
                files.add(arg);
                continue;
            }

            if (arg.startsWith(definePropPrefix)) {
                final String value = arg.substring(definePropPrefix.length());
                final int eq = value.indexOf('=');
                if (eq != -1) {
                    // -Dfoo=bar Set System property "foo" with value "bar"
                    System.setProperty(value.substring(0, eq), value.substring(eq + 1));
                } else {
                    // -Dfoo is fine. Set System property "foo" with "" as it's value
                    if (!value.isEmpty()) {
                        System.setProperty(value, "");
                    } else {
                        // do not allow empty property name
                        throw new IllegalOptionException(definePropTemplate);
                    }
                }
                continue;
            }

            // it is an argument,  it and assign key, value and template
            final ParsedArg parg = new ParsedArg(arg);

            // check if the value of this option is passed as next argument
            if (parg.template.isValueNextArg()) {
                if (argList.isEmpty()) {
                    throw new IllegalOptionException(parg.template);
                }
                parg.value = argList.remove(0);
            }

            // -h [args...]
            if (parg.template.isHelp()) {
                // check if someone wants help on an explicit arg
                if (!argList.isEmpty()) {
                    try {
                        final OptionTemplate t = new ParsedArg(argList.get(0)).template;
                        throw new IllegalOptionException(t);
                    } catch (final IllegalArgumentException e) {
                        throw e;
                    }
                }
                throw new IllegalArgumentException(); // show help for
                // everything
            }

            if (parg.template.isXHelp()) {
                throw new IllegalOptionException(parg.template);
            }

            set(parg.template.getKey(), createOption(parg.template, parg.value));

            // Arg may have a dependency to set other args, e.g.
            // scripting->anon.functions
            if (parg.template.getDependency() != null) {
                argList.addFirst(parg.template.getDependency());
            }
        }
    }

    private static void addSystemProperties(final String sysPropName, final List<String> argList) {
        final String sysArgs = getStringProperty(sysPropName, null);
        if (sysArgs != null) {
            final StringTokenizer st = new StringTokenizer(sysArgs);
            while (st.hasMoreTokens()) {
                argList.add(st.nextToken());
            }
        }
    }

    private static OptionTemplate getOptionTemplate(final String key) {
        for (final OptionTemplate t : Options.validOptions) {
            if (t.matches(key)) {
                return t;
            }
        }
        return null;
    }

    private static Option<?> createOption(final OptionTemplate t, final String value) {
        switch (t.getType()) {
        case "string":
            // default value null
            return new Option<>(value);
        case "timezone":
            // default value "TimeZone.getDefault()"
            return new Option<>(TimeZone.getTimeZone(value));
        case "locale":
            return new Option<>(Locale.forLanguageTag(value));
        case "keyvalues":
            return new KeyValueOption(value);
        case "log":
            return new LoggingOption(value);
        case "boolean":
            return new Option<>(value != null && Boolean.parseBoolean(value));
        case "integer":
            try {
                return new Option<>(value == null ? 0 : Integer.parseInt(value));
            } catch (final NumberFormatException nfe) {
                throw new IllegalOptionException(t);
            }
        case "properties":
            //swallow the properties and set them
            initProps(new KeyValueOption(value));
            return null;
        default:
            break;
        }
        throw new IllegalArgumentException(value);
    }

    private static void initProps(final KeyValueOption kv) {
        for (final Map.Entry<String, String> entry : kv.getValues().entrySet()) {
            System.setProperty(entry.getKey(), entry.getValue());
        }
    }

    /**
     * Resource name for properties file
     */
    private static final String MESSAGES_RESOURCE = "jdk.nashorn.internal.runtime.resources.Options";

    /**
     * Resource bundle for properties file
     */
    private static ResourceBundle bundle;

    /**
     * Usages per resource from properties file
     */
    private static HashMap<Object, Object> usage;

    /**
     * Valid options from templates in properties files
     */
    private static Collection<OptionTemplate> validOptions;

    /**
     * Help option
     */
    private static OptionTemplate helpOptionTemplate;

    /**
     * Define property option template.
     */
    private static OptionTemplate definePropTemplate;

    /**
     * Prefix of "define property" option.
     */
    private static String definePropPrefix;

    static {
        Options.bundle = ResourceBundle.getBundle(Options.MESSAGES_RESOURCE, Locale.getDefault());
        Options.validOptions = new TreeSet<>();
        Options.usage        = new HashMap<>();

        for (final Enumeration<String> keys = Options.bundle.getKeys(); keys.hasMoreElements(); ) {
            final String key = keys.nextElement();
            final StringTokenizer st = new StringTokenizer(key, ".");
            String resource = null;
            String type = null;

            if (st.countTokens() > 0) {
                resource = st.nextToken(); // e.g. "nashorn"
            }

            if (st.countTokens() > 0) {
                type = st.nextToken(); // e.g. "option"
            }

            if ("option".equals(type)) {
                String helpKey = null;
                String xhelpKey = null;
                String definePropKey = null;
                try {
                    helpKey = Options.bundle.getString(resource + ".options.help.key");
                    xhelpKey = Options.bundle.getString(resource + ".options.xhelp.key");
                    definePropKey = Options.bundle.getString(resource + ".options.D.key");
                } catch (final MissingResourceException e) {
                    //ignored: no help
                }
                final boolean        isHelp = key.equals(helpKey);
                final boolean        isXHelp = key.equals(xhelpKey);
                final OptionTemplate t      = new OptionTemplate(resource, key, Options.bundle.getString(key), isHelp, isXHelp);

                Options.validOptions.add(t);
                if (isHelp) {
                    helpOptionTemplate = t;
                }

                if (key.equals(definePropKey)) {
                    definePropPrefix = t.getName();
                    definePropTemplate = t;
                }
            } else if (resource != null && "options".equals(type)) {
                Options.usage.put(resource, Options.bundle.getObject(key));
            }
        }
    }

    @SuppressWarnings("serial")
    private static class IllegalOptionException extends IllegalArgumentException {
        private final OptionTemplate template;

        IllegalOptionException(final OptionTemplate t) {
            super();
            this.template = t;
        }

        OptionTemplate getTemplate() {
            return this.template;
        }
    }

    /**
     * This is a resolved argument of the form key=value
     */
    private static class ParsedArg {
        /** The resolved option template this argument corresponds to */
        OptionTemplate template;

        /** The value of the argument */
        String value;

        ParsedArg(final String argument) {
            final QuotedStringTokenizer st = new QuotedStringTokenizer(argument, "=");
            if (!st.hasMoreTokens()) {
                throw new IllegalArgumentException();
            }

            final String token = st.nextToken();
            this.template = Options.getOptionTemplate(token);
            if (this.template == null) {
                throw new IllegalArgumentException(argument);
            }

            value = "";
            if (st.hasMoreTokens()) {
                while (st.hasMoreTokens()) {
                    value += st.nextToken();
                    if (st.hasMoreTokens()) {
                        value += ':';
                    }
                }
            } else if ("boolean".equals(this.template.getType())) {
                value = "true";
            }
        }
    }
}
