// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/**
 * Parser support for transforming raw command-line arguments into a set
 * of options and values.
 *
 * This library supports [GNU][] and [POSIX][] style options, and it works
 * in both server-side and client-side apps.
 *
 * For information on installing this library, see the
 * [args package on pub.dartlang.org](http://pub.dartlang.org/packages/args).
 * Here's an example of importing this library:
 *
 *     import 'package:args/args.dart';
 *
 * ## Defining options
 *
 * To use this library, first create an [ArgParser]:
 *
 *     var parser = new ArgParser();
 *
 * Then define a set of options on that parser using [addOption()] and
 * [addFlag()]. Here's the minimal way to create an option named "name":
 *
 *     parser.addOption('name');
 *
 * When an option can only be set or unset (as opposed to taking a string
 * value), use a flag:
 *
 *     parser.addFlag('name');
 *
 * Flag options, by default, accept a 'no-' prefix to negate the option.
 * You can disable the 'no-' prefix using the `negatable` parameter:
 *
 *     parser.addFlag('name', negatable: false);
 *
 * **Terminology note:**
 * From here on out, the term _option_ refers to both regular options and
 * flags. In cases where the distinction matters, this documentation uses
 * the term _non-flag option._
 *
 * Options can have an optional single-character abbreviation, specified
 * with the `abbr` parameter:
 *
 *     parser.addOption('mode', abbr: 'm');
 *     parser.addFlag('verbose', abbr: 'v');
 *
 * Options can also have a default value, specified with the `defaultsTo`
 * parameter. The default value is used when arguments don't specify the
 * option.
 *
 *     parser.addOption('mode', defaultsTo: 'debug');
 *     parser.addFlag('verbose', defaultsTo: false);
 *
 * The default value for non-flag options can be any [String]. For flags,
 * it must be a [bool].
 *
 * To validate a non-flag option, you can use the `allowed` parameter to
 * provide an allowed set of values. When you do, the parser throws a
 * [FormatException] if the value for an option is not in the allowed set.
 * Here's an example of specifying allowed values:
 *
 *     parser.addOption('mode', allowed: ['debug', 'release']);
 *
 * You can use the `callback` parameter to associate a function with an
 * option. Later, when parsing occurs, the callback function is invoked
 * with the value of the option:
 *
 *     parser.addOption('mode', callback: (mode) => print('Got mode $mode));
 *     parser.addFlag('verbose', callback: (verbose) {
 *       if (verbose) print('Verbose');
 *     });
 *
 * The callbacks for all options are called whenever a set of arguments
 * is parsed. If an option isn't provided in the args, its callback is
 * passed the default value, or `null` if no default value is set.
 *
 * ## Parsing arguments
 *
 * Once you have an [ArgParser] set up with some options and flags, you
 * use it by calling [ArgParser.parse()] with a set of arguments:
 *
 *     var results = parser.parse(['some', 'command', 'line', 'args']);
 *
 * These arguments usually come from dart:io's Options class
 * (`new Options().arguments`), but you can pass in any list of strings.
 * The parse() method returns an instance of [ArgResults], a map-like
 * object that contains the values of the parsed options.
 *
 *     var parser = new ArgParser();
 *     parser.addOption('mode');
 *     parser.addFlag('verbose', defaultsTo: true);
 *     var results = parser.parse(['--mode', 'debug', 'something', 'else']);
 *
 *     print(results['mode']); // debug
 *     print(results['verbose']); // true
 *
 * By default, the parse() method stops as soon as it reaches `--` by itself
 * or anything that the parser doesn't recognize as an option, flag, or
 * option value. If arguments still remain, they go into [ArgResults.rest].
 *
 *     print(results.rest); // ['something', 'else']
 *
 * To continue to parse options found after non-option arguments, call
 * parse() with `allowTrailingOptions: true`.
 *
 * ## Specifying options
 *
 * To actually pass in options and flags on the command line, use GNU or
 * POSIX style. Consider this option:
 *
 *     parser.addOption('name', abbr: 'n');
 *
 * You can specify its value on the command line using any of the following:
 *
 *     --name=somevalue
 *     --name somevalue
 *     -nsomevalue
 *     -n somevalue
 *
 * Consider this flag:
 *
 *     parser.addFlag('name', abbr: 'n');
 *
 * You can set it to true using one of the following:
 *
 *     --name
 *     -n
 *
 * You can set it to false using the following:
 *
 *     --no-name
 *
 * Multiple flag abbreviations can be collapsed into a single argument. Say
 * you define these flags:
 *
 *     parser.addFlag('verbose', abbr: 'v');
 *     parser.addFlag('french', abbr: 'f');
 *     parser.addFlag('iambic-pentameter', abbr: 'i');
 *
 * You can set all three flags at once:
 *
 *     -vfi
 *
 * By default, an option has only a single value, with later option values
 * overriding earlier ones; for example:
 *
 *     var parser = new ArgParser();
 *     parser.addOption('mode');
 *     var results = parser.parse(['--mode', 'on', '--mode', 'off']);
 *     print(results['mode']); // prints 'off'
 *
 * If you need multiple values, set the `allowMultiple` parameter. In that
 * case the option can occur multiple times, and the parse() method returns
 * a list of values:
 *
 *     var parser = new ArgParser();
 *     parser.addOption('mode', allowMultiple: true);
 *     var results = parser.parse(['--mode', 'on', '--mode', 'off']);
 *     print(results['mode']); // prints '[on, off]'
 *
 * ## Defining commands ##
 *
 * In addition to *options*, you can also define *commands*. A command is
 * a named argument that has its own set of options. For example, consider
 * this shell command:
 *
 *     $ git commit -a
 *
 * The executable is `git`, the command is `commit`, and the `-a` option is
 * an option passed to the command. You can add a command using the
 * [addCommand] method:
 *
 *     var parser = new ArgParser();
 *     var command = parser.addCommand('commit');
 *
 * The addCommand() method returns another [ArgParser], which you can then
 * use to define options specific to that command. If you already have an
 * [ArgParser] for the command's options, you can pass it to addCommand:
 *
 *     var parser = new ArgParser();
 *     var command = new ArgParser();
 *     parser.addCommand('commit', command);
 *
 * The [ArgParser] for a command can then define options or flags:
 *
 *     command.addFlag('all', abbr: 'a');
 *
 * You can add multiple commands to the same parser so that a user can select
 * one from a range of possible commands. When parsing an argument list,
 * you can then determine which command was entered and what options were
 * provided for it.
 *
 *     var results = parser.parse(['commit', '-a']);
 *     print(results.command.name);   // "commit"
 *     print(results.command['all']); // true
 *
 * Options for a command must appear after the command in the argument list.
 * For example, given the above parser, "git -a commit" is *not* valid. The
 * parser tries to find the right-most command that accepts an option. For
 * example:
 *
 *     var parser = new ArgParser();
 *     parser.addFlag('all', abbr: 'a');
 *     var command = parser.addCommand('commit');
 *     command.addFlag('all', abbr: 'a');
 *
 *     var results = parser.parse(['commit', '-a']);
 *     print(results.command['all']); // true
 *
 * Here, both the top-level parser and the "commit" command can accept a
 * "-a" (which is probably a bad command line interface, admittedly). In
 * that case, when "-a" appears after "commit", it is applied to that
 * command. If it appears to the left of "commit", it is given to the
 * top-level parser.
 *
 * ## Displaying usage
 *
 * You can automatically generate nice help text, suitable for use as the
 * output of `--help`. To display good usage information, you should
 * provide some help text when you create your options.
 *
 * To define help text for an entire option, use the `help` parameter:
 *
 *     parser.addOption('mode', help: 'The compiler configuration',
 *         allowed: ['debug', 'release']);
 *     parser.addFlag('verbose', help: 'Show additional diagnostic info');
 *
 * For non-flag options, you can also provide detailed help for each expected
 * value by using the `allowedHelp` parameter:
 *
 *     parser.addOption('arch', help: 'The architecture to compile for',
 *         allowedHelp: {
 *           'ia32': 'Intel x86',
 *           'arm': 'ARM Holding 32-bit chip'
 *         });
 *
 * To display the help, use the ArgParser getUsage() method:
 *
 *     print(parser.getUsage());
 * 
 * The resulting string looks something like this:
 *
 *     --mode            The compiler configuration
 *                       [debug, release]
 *
 *     --[no-]verbose    Show additional diagnostic info
 *     --arch            The architecture to compile for
 *
 *           [arm]       ARM Holding 32-bit chip
 *           [ia32]      Intel x86
 *
 * To assist the formatting of the usage help, single-line help text is
 * followed by a single new line. Options with multi-line help text are
 * followed by two new lines. This provides spatial diversity between options.
 *
 * [posix]: http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap12.html#tag_12_02
 * [gnu]: http://www.gnu.org/prep/standards/standards.html#Command_002dLine-Interfaces
 */
library args;

import 'package:unmodifiable_collection/unmodifiable_collection.dart';

import 'src/parser.dart';
import 'src/usage.dart';
import 'src/options.dart';
export 'src/options.dart';

/**
 * A class for taking a list of raw command line arguments and parsing out
 * options and flags from them.
 */
class ArgParser {
  final Map<String, Option> _options;
  final Map<String, ArgParser> _commands;

  /**
   * The options that have been defined for this parser.
   */
  final Map<String, Option> options;

  /**
   * The commands that have been defined for this parser.
   */
  final Map<String, ArgParser> commands;

  /** Creates a new ArgParser. */
  factory ArgParser() =>
      new ArgParser._(<String, Option>{}, <String, ArgParser>{});

  ArgParser._(Map<String, Option> options, Map<String, ArgParser> commands) :
    this._options = options,
    this.options = new UnmodifiableMapView(options),
    this._commands = commands,
    this.commands = new UnmodifiableMapView(commands);

  /**
   * Defines a command.
   *
   * A command is a named argument which may in turn define its own options and
   * subcommands using the given parser. If [parser] is omitted, implicitly
   * creates a new one. Returns the parser for the command.
   */
  ArgParser addCommand(String name, [ArgParser parser]) {
    // Make sure the name isn't in use.
    if (_commands.containsKey(name)) {
      throw new ArgumentError('Duplicate command "$name".');
    }

    if (parser == null) parser = new ArgParser();
    _commands[name] = parser;
    return parser;
  }

  /**
   * Defines a flag. Throws an [ArgumentError] if:
   *
   * * There is already an option named [name].
   * * There is already an option using abbreviation [abbr].
   */
  void addFlag(String name, {String abbr, String help, bool defaultsTo: false,
      bool negatable: true, void callback(bool value)}) {
    _addOption(name, abbr, help, null, null, defaultsTo, callback,
        isFlag: true, negatable: negatable);
  }

  /**
   * Defines a value-taking option. Throws an [ArgumentError] if:
   *
   * * There is already an option with name [name].
   * * There is already an option using abbreviation [abbr].
   */
  void addOption(String name, {String abbr, String help, List<String> allowed,
      Map<String, String> allowedHelp, String defaultsTo,
      void callback(value), bool allowMultiple: false}) {
    _addOption(name, abbr, help, allowed, allowedHelp, defaultsTo,
        callback, isFlag: false, allowMultiple: allowMultiple);
  }

  void _addOption(String name, String abbr, String help, List<String> allowed,
      Map<String, String> allowedHelp, defaultsTo,
      void callback(value), {bool isFlag, bool negatable: false,
      bool allowMultiple: false}) {
    // Make sure the name isn't in use.
    if (_options.containsKey(name)) {
      throw new ArgumentError('Duplicate option "$name".');
    }

    // Make sure the abbreviation isn't too long or in use.
    if (abbr != null) {
      var existing = findByAbbreviation(abbr);
      if (existing != null) {
        throw new ArgumentError(
            'Abbreviation "$abbr" is already used by "${existing.name}".');
      }
    }

    _options[name] = new Option(name, abbr, help, allowed, allowedHelp,
        defaultsTo, callback, isFlag: isFlag, negatable: negatable,
        allowMultiple: allowMultiple);
  }

  /**
   * Parses [args], a list of command-line arguments, matches them against the
   * flags and options defined by this parser, and returns the result.
   *
   * If [allowTrailingOptions] is set, the parser will continue parsing even
   * after it finds an argument that is neither an option nor a command.
   * This allows options to be specified after regular arguments.
   *
   * [allowTrailingOptions] is false by default, so when a non-option,
   * non-command argument is encountered, it and all remaining arguments,
   * even those that look like options are passed to the innermost command.
   */
  ArgResults parse(List<String> args, {bool allowTrailingOptions}) {
    if (allowTrailingOptions == null) allowTrailingOptions = false;
    return new Parser(null, this, args.toList(), null, null,
        allowTrailingOptions: allowTrailingOptions).parse();
  }

  /**
   * Generates a string displaying usage information for the defined options.
   * This is basically the help text shown on the command line.
   */
  String getUsage() => new Usage(this).generate();

  /**
   * Get the default value for an option. Useful after parsing to test
   * if the user specified something other than the default.
   */
  getDefault(String option) {
    if (!options.containsKey(option)) {
      throw new ArgumentError('No option named $option');
    }
    return options[option].defaultValue;
  }

  /**
   * Finds the option whose abbreviation is [abbr], or `null` if no option has
   * that abbreviation.
   */
  Option findByAbbreviation(String abbr) {
    return options.values.firstWhere((option) => option.abbreviation == abbr,
        orElse: () => null);
  }
}

/**
 * The results of parsing a series of command line arguments using
 * [ArgParser.parse()]. Includes the parsed options and any remaining unparsed
 * command line arguments.
 */
class ArgResults {
  final Map<String, dynamic> _options;

  /**
   * If these are the results for parsing a command's options, this will be
   * the name of the command. For top-level results, this returns `null`.
   */
  final String name;

  /**
   * The command that was selected, or `null` if none was. This will contain
   * the options that were selected for that command.
   */
  final ArgResults command;

  /**
   * The remaining command-line arguments that were not parsed as options or
   * flags. If `--` was used to separate the options from the remaining
   * arguments, it will not be included in this list.
   */
  final List<String> rest;

  /** Creates a new [ArgResults]. */
  ArgResults(this._options, this.name, this.command, List<String> rest)
    : this.rest = new UnmodifiableListView(rest);

  /** Gets the parsed command-line option named [name]. */
  operator [](String name) {
    if (!_options.containsKey(name)) {
      throw new ArgumentError(
          'Could not find an option named "$name".');
    }

    return _options[name];
  }

  /** Get the names of the options as an [Iterable]. */
  Iterable<String> get options => _options.keys;
}

