// Copyright 2020 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'package:args/args.dart';

class TestArguments {
  final List<String> rawArgs;

  /// Arguments hydrated into their respective data type representations
  /// ([bool], [String], [int], etc).
  final ArgResults parsedArgs;

  /// Raw string arguments to be forwarded down to each executed test.
  ///
  /// These tokens have no impact whatsoever on how `fx test` finds, filters,
  /// and invokes tests. They are exclusively used by the underlying tests.
  final List<String> passThroughArgs;

  /// Optional strings to pretend were passed. Key-value pairs are merged into
  /// a single string in [rawArgs] if the key is not present in [rawArgs].
  /// For flags (as opposed to options), pass either `null` or an empty string
  /// as the value.
  final Map<String, String?>? defaultRawArgs;

  /// Similar to [passThroughArgs], but unique to e2e tests.
  final List<String> e2ePassThroughArgs;

  TestArguments({
    required this.rawArgs,
    required ArgParser parser,
    this.defaultRawArgs,
  })  : e2ePassThroughArgs = <String>[],
        passThroughArgs = TestArguments._extractPassThroughArgs(rawArgs),
        parsedArgs = TestArguments._parseArgs(
          rawArgs,
          parser,
          defaultRawArgs: defaultRawArgs,
        );

  /// Splits a list of command line arguments into the half intended for
  /// local use and the half intended to be passed through to sub-commands.
  static List<List<String>> splitArgs(List<String> rawArgs) {
    var dashDashIndex = rawArgs.indexOf('--');
    if (dashDashIndex == -1) {
      dashDashIndex = rawArgs.length;
    }
    return [
      rawArgs.take(dashDashIndex).toList(),
      rawArgs.skip(dashDashIndex + 1).toList(),
    ];
  }

  static List<String> _extractPassThroughArgs(List<String> rawArgs) {
    return TestArguments.splitArgs(rawArgs)[1];
  }

  static ArgResults _parseArgs(
    List<String> rawArgs,
    ArgParser parser, {
    Map<String, String?>? defaultRawArgs,
  }) {
    var localArgs = TestArguments.splitArgs(rawArgs)[0];
    localArgs = TestArguments.addDefaults(localArgs, defaultRawArgs, parser);
    return parser.parse(localArgs);
  }

  // ignore: prefer_constructors_over_static_methods
  static List<String> addDefaults(
    List<String> rawArgs,
    Map<String, String?>? defaults,
    ArgParser parser,
  ) {
    if (defaults == null || defaults.isEmpty) return rawArgs;

    var copy = List<String>.from(rawArgs);
    const String invertToken = '--no-';
    for (var key in defaults.keys) {
      // For a default of "--flag", we only want to add if there is no "--flag"
      // and no "--no-flag". The inverse is also true, for a default of
      // "--no-flag", we have to check for both "--no-flag" and "--flag".
      final oppositeKey = key.startsWith(invertToken)
          // Opposite of an invert is to drop the invert and re-apply "--".
          ? '--${key.substring(invertToken.length)}'
          // Opposite of a positive is to drop the leading "--" then add the
          // inversion token.
          : '$invertToken${key.substring(2)}';
      final keysToCheckFor = <String>{key, oppositeKey};

      // Grab the shorter key, which will be the one without a leading `--no-`.
      // We need this to check for an abbreviation.
      var primaryKey = key.length < oppositeKey.length ? key : oppositeKey;
      // Trim leading "--"
      primaryKey = primaryKey.substring(2);
      if (parser.options[primaryKey]?.abbr != null) {
        keysToCheckFor.add('-${parser.options[primaryKey]!.abbr}');
      }
      if (Set.from(rawArgs).intersection(keysToCheckFor).isEmpty) {
        copy.add(key);
        if (defaults[key] != null && defaults[key] != '') {
          copy.add(defaults[key]!);
        }
      }
    }
    return copy;
  }
}
