// 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.

import 'dart:collection';

import 'arg_parser.dart';
import 'arg_parser_exception.dart';
import 'arg_results.dart';
import 'option.dart';

/// The actual argument parsing class.
///
/// Unlike [ArgParser] which is really more an "arg grammar", this is the class
/// that does the parsing and holds the mutable state required during a parse.
class Parser {
  /// If parser is parsing a command's options, this will be the name of the
  /// command. For top-level results, this returns `null`.
  final String? commandName;

  /// The parser for the supercommand of this command parser, or `null` if this
  /// is the top-level parser.
  final Parser? parent;

  /// The grammar being parsed.
  final ArgParser grammar;

  /// The arguments being parsed.
  final Queue<String> args;

  /// The remaining non-option, non-command arguments.
  final rest = <String>[];

  /// The accumulated parsed options.
  final Map<String, dynamic> results = <String, dynamic>{};

  Parser(this.commandName, this.grammar, this.args,
      [this.parent, List<String>? rest]) {
    if (rest != null) this.rest.addAll(rest);
  }

  /// The current argument being parsed.
  String get current => args.first;

  /// Parses the arguments. This can only be called once.
  ArgResults parse() {
    var arguments = args.toList();
    if (grammar.allowsAnything) {
      return newArgResults(
          grammar, const {}, commandName, null, arguments, arguments);
    }

    ArgResults? commandResults;

    // Parse the args.
    while (args.isNotEmpty) {
      if (current == '--') {
        // Reached the argument terminator, so stop here.
        args.removeFirst();
        break;
      }

      // Try to parse the current argument as a command. This happens before
      // options so that commands can have option-like names.
      var command = grammar.commands[current];
      if (command != null) {
        validate(rest.isEmpty, 'Cannot specify arguments before a command.');
        var commandName = args.removeFirst();
        var commandParser = Parser(commandName, command, args, this, rest);

        try {
          commandResults = commandParser.parse();
        } on ArgParserException catch (error) {
          throw ArgParserException(
              error.message, [commandName, ...error.commands]);
        }

        // All remaining arguments were passed to command so clear them here.
        rest.clear();
        break;
      }

      // Try to parse the current argument as an option. Note that the order
      // here matters.
      if (parseSoloOption()) continue;
      if (parseAbbreviation(this)) continue;
      if (parseLongOption()) continue;

      // This argument is neither option nor command, so stop parsing unless
      // the [allowTrailingOptions] option is set.
      if (!grammar.allowTrailingOptions) break;
      rest.add(args.removeFirst());
    }

    // Invoke the callbacks.
    grammar.options.forEach((name, option) {
      var callback = option.callback;
      if (callback != null) callback(option.valueOrDefault(results[name]));
    });

    // Add in the leftover arguments we didn't parse to the innermost command.
    rest.addAll(args);
    args.clear();
    return newArgResults(
        grammar, results, commandName, commandResults, rest, arguments);
  }

  /// Pulls the value for [option] from the second argument in [args].
  ///
  /// Validates that there is a valid value there.
  void readNextArgAsValue(Option option) {
    // Take the option argument from the next command line arg.
    validate(args.isNotEmpty, 'Missing argument for "${option.name}".');

    setOption(results, option, current);
    args.removeFirst();
  }

  /// Tries to parse the current argument as a "solo" option, which is a single
  /// hyphen followed by a single letter.
  ///
  /// We treat this differently than collapsed abbreviations (like "-abc") to
  /// handle the possible value that may follow it.
  bool parseSoloOption() {
    // Hand coded regexp: r'^-([a-zA-Z0-9])$'
    // Length must be two, hyphen followed by any letter/digit.
    if (current.length != 2) return false;
    if (!current.startsWith('-')) return false;
    var opt = current[1];
    if (!_isLetterOrDigit(opt.codeUnitAt(0))) return false;

    var option = grammar.findByAbbreviation(opt);
    if (option == null) {
      // Walk up to the parent command if possible.
      validate(parent != null, 'Could not find an option or flag "-$opt".');
      return parent!.parseSoloOption();
    }

    args.removeFirst();

    if (option.isFlag) {
      setFlag(results, option, true);
    } else {
      readNextArgAsValue(option);
    }

    return true;
  }

  /// Tries to parse the current argument as a series of collapsed abbreviations
  /// (like "-abc") or a single abbreviation with the value directly attached
  /// to it (like "-mrelease").
  bool parseAbbreviation(Parser innermostCommand) {
    // Hand coded regexp: r'^-([a-zA-Z0-9]+)(.*)$'
    // Hyphen then at least one letter/digit then zero or more
    // anything-but-newlines.
    if (current.length < 2) return false;
    if (!current.startsWith('-')) return false;

    // Find where we go from letters/digits to rest.
    var index = 1;
    while (
        index < current.length && _isLetterOrDigit(current.codeUnitAt(index))) {
      ++index;
    }
    // Must be at least one letter/digit.
    if (index == 1) return false;

    // If the first character is the abbreviation for a non-flag option, then
    // the rest is the value.
    var lettersAndDigits = current.substring(1, index);
    var rest = current.substring(index);
    if (rest.contains('\n') || rest.contains('\r')) return false;

    var c = lettersAndDigits.substring(0, 1);
    var first = grammar.findByAbbreviation(c);
    if (first == null) {
      // Walk up to the parent command if possible.
      validate(
          parent != null, 'Could not find an option with short name "-$c".');
      return parent!.parseAbbreviation(innermostCommand);
    } else if (!first.isFlag) {
      // The first character is a non-flag option, so the rest must be the
      // value.
      var value = '${lettersAndDigits.substring(1)}$rest';
      setOption(results, first, value);
    } else {
      // If we got some non-flag characters, then it must be a value, but
      // if we got here, it's a flag, which is wrong.
      validate(
          rest == '',
          'Option "-$c" is a flag and cannot handle value '
          '"${lettersAndDigits.substring(1)}$rest".');

      // Not an option, so all characters should be flags.
      // We use "innermostCommand" here so that if a parent command parses the
      // *first* letter, subcommands can still be found to parse the other
      // letters.
      for (var i = 0; i < lettersAndDigits.length; i++) {
        var c = lettersAndDigits.substring(i, i + 1);
        innermostCommand.parseShortFlag(c);
      }
    }

    args.removeFirst();
    return true;
  }

  void parseShortFlag(String c) {
    var option = grammar.findByAbbreviation(c);
    if (option == null) {
      // Walk up to the parent command if possible.
      validate(
          parent != null, 'Could not find an option with short name "-$c".');
      parent!.parseShortFlag(c);
      return;
    }

    // In a list of short options, only the first can be a non-flag. If
    // we get here we've checked that already.
    validate(
        option.isFlag, 'Option "-$c" must be a flag to be in a collapsed "-".');

    setFlag(results, option, true);
  }

  /// Tries to parse the current argument as a long-form named option, which
  /// may include a value like "--mode=release" or "--mode release".
  bool parseLongOption() {
    // Hand coded regexp: r'^--([a-zA-Z\-_0-9]+)(=(.*))?$'
    // Two hyphens then at least one letter/digit/hyphen, optionally an equal
    // sign followed by zero or more anything-but-newlines.

    if (!current.startsWith('--')) return false;

    var index = current.indexOf('=');
    var name = index == -1 ? current.substring(2) : current.substring(2, index);
    for (var i = 0; i != name.length; ++i) {
      if (!_isLetterDigitHyphenOrUnderscore(name.codeUnitAt(i))) return false;
    }
    var value = index == -1 ? null : current.substring(index + 1);
    if (value != null && (value.contains('\n') || value.contains('\r'))) {
      return false;
    }

    var option = grammar.options[name];
    if (option != null) {
      args.removeFirst();
      if (option.isFlag) {
        validate(
            value == null, 'Flag option "$name" should not be given a value.');

        setFlag(results, option, true);
      } else if (value != null) {
        // We have a value like --foo=bar.
        setOption(results, option, value);
      } else {
        // Option like --foo, so look for the value as the next arg.
        readNextArgAsValue(option);
      }
    } else if (name.startsWith('no-')) {
      // See if it's a negated flag.
      name = name.substring('no-'.length);
      option = grammar.options[name];
      if (option == null) {
        // Walk up to the parent command if possible.
        validate(parent != null, 'Could not find an option named "$name".');
        return parent!.parseLongOption();
      }

      args.removeFirst();
      validate(option.isFlag, 'Cannot negate non-flag option "$name".');
      validate(option.negatable!, 'Cannot negate option "$name".');

      setFlag(results, option, false);
    } else {
      // Walk up to the parent command if possible.
      validate(parent != null, 'Could not find an option named "$name".');
      return parent!.parseLongOption();
    }

    return true;
  }

  /// Called during parsing to validate the arguments.
  ///
  /// Throws an [ArgParserException] if [condition] is `false`.
  void validate(bool condition, String message) {
    if (!condition) throw ArgParserException(message);
  }

  /// Validates and stores [value] as the value for [option], which must not be
  /// a flag.
  void setOption(Map results, Option option, String value) {
    assert(!option.isFlag);

    if (!option.isMultiple) {
      _validateAllowed(option, value);
      results[option.name] = value;
      return;
    }

    var list = results.putIfAbsent(option.name, () => <String>[]);

    if (option.splitCommas) {
      for (var element in value.split(',')) {
        _validateAllowed(option, element);
        list.add(element);
      }
    } else {
      _validateAllowed(option, value);
      list.add(value);
    }
  }

  /// Validates and stores [value] as the value for [option], which must be a
  /// flag.
  void setFlag(Map results, Option option, bool value) {
    assert(option.isFlag);
    results[option.name] = value;
  }

  /// Validates that [value] is allowed as a value of [option].
  void _validateAllowed(Option option, String value) {
    if (option.allowed == null) return;

    validate(option.allowed!.contains(value),
        '"$value" is not an allowed value for option "${option.name}".');
  }
}

bool _isLetterOrDigit(int codeUnit) =>
    // Uppercase letters.
    (codeUnit >= 65 && codeUnit <= 90) ||
    // Lowercase letters.
    (codeUnit >= 97 && codeUnit <= 122) ||
    // Digits.
    (codeUnit >= 48 && codeUnit <= 57);

bool _isLetterDigitHyphenOrUnderscore(int codeUnit) =>
    _isLetterOrDigit(codeUnit) ||
    // Hyphen.
    codeUnit == 45 ||
    // Underscore.
    codeUnit == 95;
