/**
 * 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 backtype.storm;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStreamReader;
import java.io.IOException;
import java.io.PrintStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.LinkedHashMap;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.yaml.snakeyaml.Yaml;

/**
 * <code>GenericOptionsParser</code> is a utility to parse command line arguments generic to Storm.
 * 
 * <code>GenericOptionsParser</code> recognizes several standard command line arguments, enabling applications to easily specify additional jar files,
 * configuration resources, data files etc.
 * 
 * <h4 id="GenericOptions">Generic Options</h4>
 * 
 * <p>
 * The supported generic options are:
 * </p>
 * <p>
 * <blockquote>
 * 
 * <pre>
 * -conf &lt;conf.xml&gt;                           load configurations from
 *                                            &lt;conf.xml&gt;
 * -conf &lt;conf.yaml&gt;                          load configurations from
 *                                            &lt;conf.yaml&gt;
 * -D &lt;key=value&gt;                             set &lt;key&gt; in configuration to
 *                                            &lt;value&gt; (preserve value's type)
 * -libjars &lt;comma separated list of jars&gt;    specify comma separated jars to be
 *                                            used by the submitted topology
 * </pre>
 * 
 * </blockquote>
 * </p>
 * 
 * <b>Note:</b> The XML configuration file specified by <code>-conf</code> shall be readable by Hadoop's <a href=
 * "http://hadoop.apache.org/docs/current/api/org/apache/hadoop/conf/Configuration.html" ><code>Configuration</code></a> class. Also note that all configuration
 * values of an XML file will be treated as strings, and <b>not as specific types</b>.
 * 
 * <p>
 * The general command line syntax is:
 * </p>
 * <p>
 * <tt><pre>
 *     storm jar app.jar [genericOptions] [commandOptions]
 * </pre></tt>
 * </p>
 * 
 * <p>
 * Generic command line arguments <strong>might</strong> modify <code>Config</code> objects, given to constructors.
 * </p>
 * 
 * <h4>Configuration priority</h4>
 * 
 * The following list defines the priorities of different configuration sources, in ascending order. Thus, if a configuration appears in more than one of them,
 * only the last one will take effect.
 * 
 * <ul>
 * <li> <code>defaults.yaml</code> in classpath.
 * <li> <code>storm.yaml</code> in classpath.
 * <li>Configurations from files specified with the <code>-conf</code> option, in the order of appearance.
 * <li>Configurations defined with the <code>-D</code> option, in order of appearance.
 * </ul>
 * 
 * <p>
 * The functionality is implemented using Commons CLI.
 * </p>
 * 
 * @see Tool
 * @see ToolRunner
 */

public class GenericOptionsParser {
    static final Logger LOG = LoggerFactory.getLogger(GenericOptionsParser.class);

    static final Charset UTF8 = Charset.forName("UTF-8");

    public static final String TOPOLOGY_LIB_PATH = "topology.lib.path";

    public static final String TOPOLOGY_LIB_NAME = "topology.lib.name";

    Config conf;

    CommandLine commandLine;

    // Order in this map is important for these purposes:
    // - configuration priority
    static final LinkedHashMap<String, OptionProcessor> optionProcessors = new LinkedHashMap<String, OptionProcessor>();

    public GenericOptionsParser(Config conf, String[] args) throws ParseException {
        this(conf, new Options(), args);
    }

    public GenericOptionsParser(Config conf, Options options, String[] args) throws ParseException {
        this.conf = conf;
        parseGeneralOptions(options, conf, args);
    }

    public String[] getRemainingArgs() {
        return commandLine.getArgs();
    }

    public Config getConfiguration() {
        return conf;
    }

    static Options buildGeneralOptions(Options opts) {
        Options r = new Options();

        for (Object o : opts.getOptions())
            r.addOption((Option) o);

        Option libjars =
                OptionBuilder.withArgName("paths").hasArg().withDescription("comma separated jars to be used by the submitted topology").create("libjars");
        r.addOption(libjars);
        optionProcessors.put("libjars", new LibjarsProcessor());

        Option conf = OptionBuilder.withArgName("configuration file").hasArg().withDescription("an application configuration file").create("conf");
        r.addOption(conf);
        optionProcessors.put("conf", new ConfFileProcessor());

        // Must come after `conf': this option is of higher priority
        Option extraConfig = OptionBuilder.withArgName("D").hasArg().withDescription("extra configurations (preserving types)").create("D");
        r.addOption(extraConfig);
        optionProcessors.put("D", new ExtraConfigProcessor());

        return r;
    }

    void parseGeneralOptions(Options opts, Config conf, String[] args) throws ParseException {
        opts = buildGeneralOptions(opts);
        CommandLineParser parser = new GnuParser();
        commandLine = parser.parse(opts, args, true);
        processGeneralOptions(conf, commandLine);
    }

    void processGeneralOptions(Config conf, CommandLine commandLine) throws ParseException {
        for (Map.Entry<String, OptionProcessor> e : optionProcessors.entrySet())
            if (commandLine.hasOption(e.getKey()))
                e.getValue().process(conf, commandLine);
    }

    static List<File> validateFiles(String pathList) throws IOException {
        List<File> l = new ArrayList<File>();

        for (String s : pathList.split(",")) {
            File file = new File(s);
            if (!file.exists())
                throw new FileNotFoundException("File `" + file.getAbsolutePath() + "' does not exist");

            l.add(file);
        }

        return l;
    }

    public static void printGenericCommandUsage(PrintStream out) {
        String[] strs =
                new String[] { "Generic options supported are", "  -conf <conf.xml>                            load configurations from",
                        "                                              <conf.xml>", "  -conf <conf.yaml>                           load configurations from",
                        "                                              <conf.yaml>",
                        "  -D <key>=<value>                            set <key> in configuration",
                        "                                              to <value> (preserve value's type)",
                        "  -libjars <comma separated list of jars>     specify comma separated",
                        "                                              jars to be used by",
                        "                                              the submitted topology", };
        for (String s : strs)
            out.println(s);
    }

    static interface OptionProcessor {
        public void process(Config conf, CommandLine commandLine) throws ParseException;
    }

    static class LibjarsProcessor implements OptionProcessor {
        @Override
        public void process(Config conf, CommandLine commandLine) throws ParseException {
            try {
                List<File> jarFiles = validateFiles(commandLine.getOptionValue("libjars"));
                Map<String, String> jars = new HashMap<String, String>(jarFiles.size());
                List<String> names = new ArrayList<String>(jarFiles.size());
                for (File f : jarFiles) {
                    jars.put(f.getName(), f.getAbsolutePath());
                    names.add(f.getName());
                }
                conf.put(TOPOLOGY_LIB_PATH, jars);
                conf.put(TOPOLOGY_LIB_NAME, names);

            } catch (IOException e) {
                throw new ParseException(e.getMessage());
            }
        }
    }

    static class ExtraConfigProcessor implements OptionProcessor {
        static final Yaml yaml = new Yaml();

        @Override
        public void process(Config conf, CommandLine commandLine) throws ParseException {
            for (String s : commandLine.getOptionValues("D")) {
                String[] keyval = s.split("=", 2);
                if (keyval.length != 2)
                    throw new ParseException("Invalid option value `" + s + "'");

                conf.putAll((Map) yaml.load(keyval[0] + ": " + keyval[1]));
            }
        }
    }

    static class ConfFileProcessor implements OptionProcessor {
        static final Yaml yaml = new Yaml();

        static Map loadYamlConf(String f) throws IOException {
            InputStreamReader reader = null;
            try {
                FileInputStream fis = new FileInputStream(f);
                reader = new InputStreamReader(fis, UTF8);
                return (Map) yaml.load(reader);
            } finally {
                if (reader != null)
                    reader.close();
            }
        }

        static Map loadConf(String f) throws IOException {
            if (f.endsWith(".yaml"))
                return loadYamlConf(f);
            throw new IOException("Unknown configuration file type: " + f + " does not end with either .yaml");
        }

        @Override
        public void process(Config conf, CommandLine commandLine) throws ParseException {
            try {
                for (String f : commandLine.getOptionValues("conf")) {
                    Map m = loadConf(f);
                    if (m == null)
                        throw new ParseException("Empty configuration file " + f);
                    conf.putAll(m);
                }
            } catch (IOException e) {
                throw new ParseException(e.getMessage());
            }
        }
    }
}
