// Copyright (c) 2014, 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.

library args.src.arg_results;

import 'dart:collection';

import 'arg_parser.dart';

/// Creates a new [ArgResults].
///
/// Since [ArgResults] doesn't have a public constructor, this lets [Parser]
/// get to it. This function isn't exported to the public API of the package.
ArgResults newArgResults(ArgParser parser, Map<String, dynamic> parsed,
    String name, ArgResults command, List<String> rest,
    List<String> arguments) {
  return new ArgResults._(parser, parsed, name, command, rest, arguments);
}

/// 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 {
  /// The [ArgParser] whose options were parsed for these results.
  final ArgParser _parser;

  /// The option values that were parsed from arguments.
  final Map<String, dynamic> _parsed;

  /// 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 unless parsing stopped before the
  /// `--` was reached.
  final List<String> rest;

  /// The original list of arguments that were parsed.
  final List<String> arguments;

  /// Creates a new [ArgResults].
  ArgResults._(this._parser, this._parsed, this.name, this.command,
      List<String> rest, List<String> arguments)
      : this.rest = new UnmodifiableListView(rest),
        this.arguments = new UnmodifiableListView(arguments);

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

    return _parser.options[name].getOrDefault(_parsed[name]);
  }

  /// Get the names of the available options as an [Iterable].
  ///
  /// This includes the options whose values were parsed or that have defaults.
  /// Options that weren't present and have no default will be omitted.
  Iterable<String> get options {
    var result = new Set<String>.from(_parsed.keys);

    // Include the options that have defaults.
    _parser.options.forEach((name, option) {
      if (option.defaultValue != null) result.add(name);
    });

    return result;
  }

  /// Returns `true` if the option with [name] was parsed from an actual
  /// argument.
  ///
  /// Returns `false` if it wasn't provided and the default value or no default
  /// value would be used instead.
  bool wasParsed(String name) {
    var option = _parser.options[name];
    if (option == null) {
      throw new ArgumentError('Could not find an option named "$name".');
    }

    return _parsed.containsKey(name);
  }
}
