/*
 * Copyright (c) 2015, 2017, 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.tools.jlink.internal;

import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.module.Configuration;
import java.lang.module.ModuleFinder;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Map.Entry;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import jdk.tools.jlink.internal.plugins.ExcludeJmodSectionPlugin;
import jdk.tools.jlink.plugin.Plugin;
import jdk.tools.jlink.plugin.Plugin.Category;
import jdk.tools.jlink.builder.DefaultImageBuilder;
import jdk.tools.jlink.builder.ImageBuilder;
import jdk.tools.jlink.plugin.PluginException;
import jdk.tools.jlink.internal.Jlink.PluginsConfiguration;
import jdk.tools.jlink.internal.plugins.PluginsResourceBundle;
import jdk.tools.jlink.internal.plugins.DefaultCompressPlugin;
import jdk.tools.jlink.internal.plugins.StripDebugPlugin;
import jdk.internal.module.ModulePath;

/**
 *
 * JLink and JImage tools shared helper.
 */
public final class TaskHelper {

    public static final String JLINK_BUNDLE = "jdk.tools.jlink.resources.jlink";
    public static final String JIMAGE_BUNDLE = "jdk.tools.jimage.resources.jimage";

    private static final String DEFAULTS_PROPERTY = "jdk.jlink.defaults";

    public final class BadArgs extends Exception {

        static final long serialVersionUID = 8765093759964640721L;

        private BadArgs(String key, Object... args) {
            super(bundleHelper.getMessage(key, args));
            this.key = key;
            this.args = args;
        }

        public BadArgs showUsage(boolean b) {
            showUsage = b;
            return this;
        }
        public final String key;
        public final Object[] args;
        public boolean showUsage;
    }

    public static class Option<T> implements Comparable<T> {
        public interface Processing<T> {

            void process(T task, String opt, String arg) throws BadArgs;
        }

        final boolean hasArg;
        final Processing<T> processing;
        final boolean hidden;
        final String name;
        final String shortname;
        final boolean terminalOption;

        public Option(boolean hasArg,
                      Processing<T> processing,
                      boolean hidden,
                      String name,
                      String shortname,
                      boolean isTerminal)
        {
            if (!name.startsWith("--")) {
                throw new RuntimeException("option name missing --, " + name);
            }
            if (!shortname.isEmpty() && !shortname.startsWith("-")) {
                throw new RuntimeException("short name missing -, " + shortname);
            }

            this.hasArg = hasArg;
            this.processing = processing;
            this.hidden = hidden;
            this.name = name;
            this.shortname = shortname;
            this.terminalOption = isTerminal;
        }

        public Option(boolean hasArg, Processing<T> processing, String name, String shortname, boolean isTerminal) {
            this(hasArg, processing, false, name, shortname, isTerminal);
        }

        public Option(boolean hasArg, Processing<T> processing, String name, String shortname) {
            this(hasArg, processing, false, name, shortname, false);
        }

        public Option(boolean hasArg, Processing<T> processing, boolean hidden, String name) {
            this(hasArg, processing, hidden, name, "", false);
        }

        public Option(boolean hasArg, Processing<T> processing, String name) {
            this(hasArg, processing, false, name, "", false);
        }

        public boolean isHidden() {
            return hidden;
        }

        public boolean isTerminal() {
            return terminalOption;
        }

        public boolean matches(String opt) {
            return opt.equals(name) ||
                   opt.equals(shortname) ||
                   hasArg && opt.startsWith("--") && opt.startsWith(name + "=");
         }

        public boolean ignoreRest() {
            return false;
        }

        void process(T task, String opt, String arg) throws BadArgs {
            processing.process(task, opt, arg);
        }

        public String getName() {
            return name;
        }

        public String resourceName() {
            return resourcePrefix() + name.substring(2);
        }

        public String getShortname() {
            return shortname;
        }

        public String resourcePrefix() {
            return "main.opt.";
        }

        @Override
        public int compareTo(Object object) {
            if (!(object instanceof Option<?>)) {
                throw new RuntimeException("comparing non-Option");
            }

            Option<?> option = (Option<?>)object;

            return name.compareTo(option.name);
        }

    }

    private static class PluginOption extends Option<PluginsHelper> {
        public PluginOption(boolean hasArg,
                Processing<PluginsHelper> processing, boolean hidden, String name, String shortname) {
            super(hasArg, processing, hidden, name, shortname, false);
        }

        public PluginOption(boolean hasArg,
                Processing<PluginsHelper> processing, boolean hidden, String name) {
            super(hasArg, processing, hidden, name, "", false);
        }

        public String resourcePrefix() {
            return "plugin.opt.";
        }
    }

    private final class PluginsHelper {

        private ModuleLayer pluginsLayer = ModuleLayer.boot();
        private final List<Plugin> plugins;
        private String lastSorter;
        private boolean listPlugins;
        private Path existingImage;

        // plugin to args maps. Each plugin may be used more than once in command line.
        // Each such occurrence results in a Map of arguments. So, there could be multiple
        // args maps per plugin instance.
        private final Map<Plugin, List<Map<String, String>>> pluginToMaps = new HashMap<>();
        private final List<PluginOption> pluginsOptions = new ArrayList<>();
        private final List<PluginOption> mainOptions = new ArrayList<>();

        private PluginsHelper(String pp) throws BadArgs {

            if (pp != null) {
                String[] dirs = pp.split(File.pathSeparator);
                List<Path> paths = new ArrayList<>(dirs.length);
                for (String dir : dirs) {
                    paths.add(Paths.get(dir));
                }

                pluginsLayer = createPluginsLayer(paths);
            }

            plugins = PluginRepository.getPlugins(pluginsLayer);

            Set<String> optionsSeen = new HashSet<>();
            for (Plugin plugin : plugins) {
                if (!Utils.isDisabled(plugin)) {
                    addOrderedPluginOptions(plugin, optionsSeen);
                }
            }
            mainOptions.add(new PluginOption(true, (task, opt, arg) -> {
                    for (Plugin plugin : plugins) {
                        if (plugin.getName().equals(arg)) {
                            pluginToMaps.remove(plugin);
                            return;
                        }
                    }
                    throw newBadArgs("err.no.such.plugin", arg);
                },
                false, "--disable-plugin"));
            mainOptions.add(new PluginOption(true, (task, opt, arg) -> {
                Path path = Paths.get(arg);
                if (!Files.exists(path) || !Files.isDirectory(path)) {
                    throw newBadArgs("err.image.must.exist", path);
                }
                existingImage = path.toAbsolutePath();
            }, true, "--post-process-path"));
            mainOptions.add(new PluginOption(true,
                    (task, opt, arg) -> {
                        lastSorter = arg;
                    },
                    true, "--resources-last-sorter"));
            mainOptions.add(new PluginOption(false,
                    (task, opt, arg) -> {
                        listPlugins = true;
                    },
                    false, "--list-plugins"));
        }

        private List<Map<String, String>> argListFor(Plugin plugin) {
            List<Map<String, String>> mapList = pluginToMaps.get(plugin);
            if (mapList == null) {
                mapList = new ArrayList<>();
                pluginToMaps.put(plugin, mapList);
            }
            return mapList;
        }

        private void addEmptyArgumentMap(Plugin plugin) {
            argListFor(plugin).add(Collections.emptyMap());
        }

        private Map<String, String> addArgumentMap(Plugin plugin) {
            Map<String, String> map = new HashMap<>();
            argListFor(plugin).add(map);
            return map;
        }

        private void addOrderedPluginOptions(Plugin plugin,
            Set<String> optionsSeen) throws BadArgs {
            String option = plugin.getOption();
            if (option == null) {
                return;
            }

            // make sure that more than one plugin does not use the same option!
            if (optionsSeen.contains(option)) {
                throw new BadArgs("err.plugin.mutiple.options",
                        option);
            }
            optionsSeen.add(option);

            PluginOption plugOption
                    = new PluginOption(plugin.hasArguments(),
                            (task, opt, arg) -> {
                                if (!Utils.isFunctional(plugin)) {
                                    throw newBadArgs("err.provider.not.functional",
                                            option);
                                }

                                if (! plugin.hasArguments()) {
                                    addEmptyArgumentMap(plugin);
                                    return;
                                }

                                Map<String, String> m = addArgumentMap(plugin);
                                // handle one or more arguments
                                if (arg.indexOf(':') == -1) {
                                    // single argument case
                                    m.put(option, arg);
                                } else {
                                    // This option can accept more than one arguments
                                    // like --option_name=arg_value:arg2=value2:arg3=value3

                                    // ":" followed by word char condition takes care of args that
                                    // like Windows absolute paths "C:\foo", "C:/foo" [cygwin] etc.
                                    // This enforces that key names start with a word character.
                                    String[] args = arg.split(":(?=\\w)", -1);
                                    String firstArg = args[0];
                                    if (firstArg.isEmpty()) {
                                        throw newBadArgs("err.provider.additional.arg.error",
                                            option, arg);
                                    }
                                    m.put(option, firstArg);
                                    // process the additional arguments
                                    for (int i = 1; i < args.length; i++) {
                                        String addArg = args[i];
                                        int eqIdx = addArg.indexOf('=');
                                        if (eqIdx == -1) {
                                            throw newBadArgs("err.provider.additional.arg.error",
                                                option, arg);
                                        }

                                        String addArgName = addArg.substring(0, eqIdx);
                                        String addArgValue = addArg.substring(eqIdx+1);
                                        if (addArgName.isEmpty() || addArgValue.isEmpty()) {
                                            throw newBadArgs("err.provider.additional.arg.error",
                                                option, arg);
                                        }
                                        m.put(addArgName, addArgValue);
                                    }
                                }
                            },
                            false, "--" + option);
            pluginsOptions.add(plugOption);

            if (Utils.isFunctional(plugin)) {
                if (Utils.isAutoEnabled(plugin)) {
                    addEmptyArgumentMap(plugin);
                }

                if (plugin instanceof DefaultCompressPlugin) {
                    plugOption
                        = new PluginOption(false,
                            (task, opt, arg) -> {
                                Map<String, String> m = addArgumentMap(plugin);
                                m.put(DefaultCompressPlugin.NAME, DefaultCompressPlugin.LEVEL_2);
                            }, false, "--compress", "-c");
                    mainOptions.add(plugOption);
                } else if (plugin instanceof StripDebugPlugin) {
                    plugOption
                        = new PluginOption(false,
                            (task, opt, arg) -> {
                                addArgumentMap(plugin);
                            }, false, "--strip-debug", "-G");
                    mainOptions.add(plugOption);
                } else if (plugin instanceof ExcludeJmodSectionPlugin) {
                    plugOption = new PluginOption(false, (task, opt, arg) -> {
                            Map<String, String> m = addArgumentMap(plugin);
                            m.put(ExcludeJmodSectionPlugin.NAME,
                                  ExcludeJmodSectionPlugin.MAN_PAGES);
                        }, false, "--no-man-pages");
                    mainOptions.add(plugOption);

                    plugOption = new PluginOption(false, (task, opt, arg) -> {
                        Map<String, String> m = addArgumentMap(plugin);
                        m.put(ExcludeJmodSectionPlugin.NAME,
                              ExcludeJmodSectionPlugin.INCLUDE_HEADER_FILES);
                    }, false, "--no-header-files");
                    mainOptions.add(plugOption);
                }
            }
        }

        private PluginOption getOption(String name) throws BadArgs {
            for (PluginOption o : pluginsOptions) {
                if (o.matches(name)) {
                    return o;
                }
            }
            for (PluginOption o : mainOptions) {
                if (o.matches(name)) {
                    return o;
                }
            }
            return null;
        }

        private PluginsConfiguration getPluginsConfig(Path output, Map<String, String> launchers
                    ) throws IOException, BadArgs {
            if (output != null) {
                if (Files.exists(output)) {
                    throw new PluginException(PluginsResourceBundle.
                            getMessage("err.dir.already.exits", output));
                }
            }

            List<Plugin> pluginsList = new ArrayList<>();
            for (Entry<Plugin, List<Map<String, String>>> entry : pluginToMaps.entrySet()) {
                Plugin plugin = entry.getKey();
                List<Map<String, String>> argsMaps = entry.getValue();

                // same plugin option may be used multiple times in command line.
                // we call configure once for each occurrence. It is upto the plugin
                // to 'merge' and/or 'override' arguments.
                for (Map<String, String> map : argsMaps) {
                    try {
                        plugin.configure(Collections.unmodifiableMap(map));
                    } catch (IllegalArgumentException e) {
                        if (JlinkTask.DEBUG) {
                            System.err.println("Plugin " + plugin.getName() + " threw exception with config: " + map);
                            e.printStackTrace();
                        }
                        throw e;
                    }
                }

                if (!Utils.isDisabled(plugin)) {
                    pluginsList.add(plugin);
                }
            }

            // recreate or postprocessing don't require an output directory.
            ImageBuilder builder = null;
            if (output != null) {
                builder = new DefaultImageBuilder(output, launchers);
            }

            return new Jlink.PluginsConfiguration(pluginsList,
                    builder, lastSorter);
        }
    }

    private static final class ResourceBundleHelper {

        private final ResourceBundle bundle;
        private final ResourceBundle pluginBundle;

        ResourceBundleHelper(String path) {
            Locale locale = Locale.getDefault();
            try {
                bundle = ResourceBundle.getBundle(path, locale);
                pluginBundle = ResourceBundle.getBundle("jdk.tools.jlink.resources.plugins", locale);
            } catch (MissingResourceException e) {
                throw new InternalError("Cannot find jlink resource bundle for locale " + locale);
            }
        }

        String getMessage(String key, Object... args) {
            String val;
            try {
                val = bundle.getString(key);
            } catch (MissingResourceException e) {
                // XXX OK, check in plugin bundle
                val = pluginBundle.getString(key);
            }
            return MessageFormat.format(val, args);
        }

    }

    public final class OptionsHelper<T> {

        private final List<Option<T>> options;
        private String[] command;
        private String defaults;

        OptionsHelper(List<Option<T>> options) {
            this.options = options;
        }

        private boolean hasArgument(String optionName) throws BadArgs {
            Option<?> opt = getOption(optionName);
            if (opt == null) {
                opt = pluginOptions.getOption(optionName);
                if (opt == null) {
                    throw new BadArgs("err.unknown.option", optionName).
                            showUsage(true);
                }
            }
            return opt.hasArg;
        }

        public boolean shouldListPlugins() {
            return pluginOptions.listPlugins;
        }

        private String getPluginsPath(String[] args) throws BadArgs {
            return null;
        }

        /**
         * Handles all options.  This method stops processing the argument
         * at the first non-option argument i.e. not starts with `-`, or
         * at the first terminal option and returns the remaining arguments,
         * if any.
         */
        public List<String> handleOptions(T task, String[] args) throws BadArgs {
            // findbugs warning, copy instead of keeping a reference.
            command = Arrays.copyOf(args, args.length);

            // Must extract it prior to do any option analysis.
            // Required to interpret custom plugin options.
            // Unit tests can call Task multiple time in same JVM.
            pluginOptions = new PluginsHelper(null);

            // process options
            for (int i = 0; i < args.length; i++) {
                if (args[i].startsWith("-")) {
                    String name = args[i];
                    PluginOption pluginOption = null;
                    Option<T> option = getOption(name);
                    if (option == null) {
                        pluginOption = pluginOptions.getOption(name);
                        if (pluginOption == null) {
                            throw new BadArgs("err.unknown.option", name).
                                    showUsage(true);
                        }
                    }
                    Option<?> opt = pluginOption == null ? option : pluginOption;
                    String param = null;
                    if (opt.hasArg) {
                        if (name.startsWith("--") && name.indexOf('=') > 0) {
                            param = name.substring(name.indexOf('=') + 1,
                                    name.length());
                        } else if (i + 1 < args.length) {
                            param = args[++i];
                        }
                        if (param == null || param.isEmpty()
                                || (param.length() >= 2 && param.charAt(0) == '-'
                                && param.charAt(1) == '-')) {
                            throw new BadArgs("err.missing.arg", name).
                                    showUsage(true);
                        }
                    }
                    if (pluginOption != null) {
                        pluginOption.process(pluginOptions, name, param);
                    } else {
                        option.process(task, name, param);
                        if (option.isTerminal()) {
                            return ++i < args.length
                                        ? Stream.of(Arrays.copyOfRange(args, i, args.length))
                                                .collect(Collectors.toList())
                                        : Collections.emptyList();

                        }
                    }
                    if (opt.ignoreRest()) {
                        i = args.length;
                    }
                } else {
                    return Stream.of(Arrays.copyOfRange(args, i, args.length))
                                 .collect(Collectors.toList());
                }
            }
            return Collections.emptyList();
        }

        private Option<T> getOption(String name) {
            for (Option<T> o : options) {
                if (o.matches(name)) {
                    return o;
                }
            }
            return null;
        }

        public void showHelp(String progName) {
            log.println(bundleHelper.getMessage("main.usage", progName));
            Stream.concat(options.stream(), pluginOptions.mainOptions.stream())
                .filter(option -> !option.isHidden())
                .sorted()
                .forEach(option -> {
                     log.println(bundleHelper.getMessage(option.resourceName()));
                });

            log.println(bundleHelper.getMessage("main.command.files"));
        }

        public void listPlugins() {
            log.println("\n" + bundleHelper.getMessage("main.extended.help"));
            List<Plugin> pluginList = PluginRepository.
                    getPlugins(pluginOptions.pluginsLayer);

            for (Plugin plugin : Utils.getSortedPlugins(pluginList)) {
                showPlugin(plugin, log);
            }

            log.println("\n" + bundleHelper.getMessage("main.extended.help.footer"));
        }

        private void showPlugin(Plugin plugin, PrintWriter log) {
            if (showsPlugin(plugin)) {
                log.println("\n" + bundleHelper.getMessage("main.plugin.name")
                        + ": " + plugin.getName());

                // print verbose details for non-builtin plugins
                if (!Utils.isBuiltin(plugin)) {
                    log.println(bundleHelper.getMessage("main.plugin.class")
                         + ": " + plugin.getClass().getName());
                    log.println(bundleHelper.getMessage("main.plugin.module")
                         + ": " + plugin.getClass().getModule().getName());
                    Category category = plugin.getType();
                    log.println(bundleHelper.getMessage("main.plugin.category")
                         + ": " + category.getName());
                    log.println(bundleHelper.getMessage("main.plugin.state")
                        + ": " + plugin.getStateDescription());
                }

                String option = plugin.getOption();
                if (option != null) {
                    log.println(bundleHelper.getMessage("main.plugin.option")
                        + ": --" + plugin.getOption()
                        + (plugin.hasArguments()? ("=" + plugin.getArgumentsDescription()) : ""));
                }

                // description can be long spanning more than one line and so
                // print a newline after description label.
                log.println(bundleHelper.getMessage("main.plugin.description")
                        + ": " + plugin.getDescription());
            }
        }

        String[] getInputCommand() {
            return command;
        }

        String getDefaults() {
            return defaults;
        }

        public ModuleLayer getPluginsLayer() {
            return pluginOptions.pluginsLayer;
        }
    }

    private PluginsHelper pluginOptions;
    private PrintWriter log;
    private final ResourceBundleHelper bundleHelper;

    public TaskHelper(String path) {
        if (!JLINK_BUNDLE.equals(path) && !JIMAGE_BUNDLE.equals(path)) {
            throw new IllegalArgumentException("Invalid Bundle");
        }
        this.bundleHelper = new ResourceBundleHelper(path);
    }

    public <T> OptionsHelper<T> newOptionsHelper(Class<T> clazz,
            Option<?>[] options) {
        List<Option<T>> optionsList = new ArrayList<>();
        for (Option<?> o : options) {
            @SuppressWarnings("unchecked")
            Option<T> opt = (Option<T>) o;
            optionsList.add(opt);
        }
        return new OptionsHelper<>(optionsList);
    }

    public BadArgs newBadArgs(String key, Object... args) {
        return new BadArgs(key, args);
    }

    public String getMessage(String key, Object... args) {
        return bundleHelper.getMessage(key, args);
    }

    public void setLog(PrintWriter log) {
        this.log = log;
    }

    public void reportError(String key, Object... args) {
        log.println(bundleHelper.getMessage("error.prefix") + " "
                + bundleHelper.getMessage(key, args));
    }

    public void reportUnknownError(String message) {
        log.println(bundleHelper.getMessage("error.prefix") + " " + message);
    }

    public void warning(String key, Object... args) {
        log.println(bundleHelper.getMessage("warn.prefix") + " "
                + bundleHelper.getMessage(key, args));
    }

    public PluginsConfiguration getPluginsConfig(Path output, Map<String, String> launchers)
            throws IOException, BadArgs {
        return pluginOptions.getPluginsConfig(output, launchers);
    }

    public Path getExistingImage() {
        return pluginOptions.existingImage;
    }

    public void showVersion(boolean full) {
        log.println(version(full ? "full" : "release"));
    }

    public String version(String key) {
        return System.getProperty("java.version");
    }

    static ModuleLayer createPluginsLayer(List<Path> paths) {

        Path[] dirs = paths.toArray(new Path[0]);
        ModuleFinder finder = ModulePath.of(Runtime.version(), true, dirs);
        Configuration bootConfiguration = ModuleLayer.boot().configuration();
        try {
            Configuration cf = bootConfiguration
                .resolveAndBind(ModuleFinder.of(),
                                finder,
                                Collections.emptySet());
            ClassLoader scl = ClassLoader.getSystemClassLoader();
            return ModuleLayer.boot().defineModulesWithOneLoader(cf, scl);
        } catch (Exception ex) {
            // Malformed plugin modules (e.g.: same package in multiple modules).
            throw new PluginException("Invalid modules in the plugins path: " + ex);
        }
    }

    // Display all plugins
    private static boolean showsPlugin(Plugin plugin) {
        return (!Utils.isDisabled(plugin) && plugin.getOption() != null);
    }
}
