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

// @dart=2.9

library fasta.tool.command_line;

import 'dart:io' show exit;

import 'package:_fe_analyzer_shared/src/messages/severity.dart' show Severity;

import 'package:build_integration/file_system/single_root.dart'
    show SingleRootFileSystem;

import 'package:front_end/src/api_prototype/compiler_options.dart'
    show CompilerOptions, parseExperimentalFlags;
import 'package:front_end/src/api_prototype/compiler_options.dart';

import 'package:front_end/src/api_prototype/experimental_flags.dart'
    show ExperimentalFlag, isExperimentEnabled;

import 'package:front_end/src/api_prototype/file_system.dart' show FileSystem;

import 'package:front_end/src/api_prototype/standard_file_system.dart'
    show StandardFileSystem;
import 'package:front_end/src/api_prototype/terminal_color_support.dart';
import 'package:front_end/src/base/nnbd_mode.dart';

import 'package:front_end/src/base/processed_options.dart'
    show ProcessedOptions;

import 'package:front_end/src/compute_platform_binaries_location.dart'
    show computePlatformBinariesLocation, computePlatformDillName;

import 'package:front_end/src/fasta/compiler_context.dart' show CompilerContext;

import 'package:front_end/src/base/command_line_options.dart';

import 'package:front_end/src/fasta/fasta_codes.dart'
    show
        Message,
        PlainAndColorizedString,
        messageFastaUsageLong,
        messageFastaUsageShort,
        templateFastaCLIArgumentRequired,
        templateUnspecified;

import 'package:front_end/src/fasta/problems.dart' show DebugAbort;

import 'package:front_end/src/fasta/resolve_input_uri.dart'
    show resolveInputUri;

import 'package:front_end/src/scheme_based_file_system.dart'
    show SchemeBasedFileSystem;

import 'package:kernel/target/targets.dart'
    show LateLowering, Target, getTarget, TargetFlags, targets;

class CommandLineProblem {
  final Message message;

  CommandLineProblem(this.message);

  CommandLineProblem.deprecated(String message)
      : this(templateUnspecified.withArguments(message));
}

class ParsedArguments {
  final Map<String, dynamic> options = <String, dynamic>{};
  final List<String> arguments = <String>[];
  final Map<String, String> defines = <String, String>{};

  toString() => "ParsedArguments($options, $arguments)";

  /// Parses a list of command-line [arguments] into options and arguments.
  ///
  /// An /option/ is something that, normally, starts with `-` or `--` (one or
  /// two dashes). However, as a special case `/?` and `/h` are also recognized
  /// as options for increased compatibility with Windows. An option can have a
  /// value.
  ///
  /// An /argument/ is something that isn't an option, for example, a file name.
  ///
  /// The specification is a map of options to one of the following values:
  /// * the type literal `Uri`, representing an option value of type [Uri],
  /// * the type literal `int`, representing an option value of type [int],
  /// * the bool literal `false`, representing a boolean option that is turned
  ///   off by default,
  /// * the bool literal `true, representing a boolean option that is turned on
  ///   by default,
  /// * or the string literal `","`, representing a comma-separated list of
  ///   values.
  ///
  /// If [arguments] contains `"--"`, anything before is parsed as options, and
  /// arguments; anything following is treated as arguments (even if starting
  /// with, for example, a `-`).
  ///
  /// If an option isn't found in [specification], an error is thrown.
  ///
  /// Boolean options do not require an option value, but an optional value can
  /// be provided using the forms `--option=value` where `value` can be `true`
  /// or `yes` to turn on the option, or `false` or `no` to turn it off.  If no
  /// option value is specified, a boolean option is turned on.
  ///
  /// All other options require an option value, either on the form `--option
  /// value` or `--option=value`.
  static ParsedArguments parse(
      List<String> arguments, Map<String, ValueSpecification> specification) {
    specification ??= const <String, ValueSpecification>{};
    ParsedArguments result = new ParsedArguments();
    int index = arguments.indexOf("--");
    Iterable<String> nonOptions = const <String>[];
    Iterator<String> iterator = arguments.iterator;
    if (index != -1) {
      nonOptions = arguments.skip(index + 1);
      iterator = arguments.take(index).iterator;
    }
    while (iterator.moveNext()) {
      String argument = iterator.current;
      if (argument.startsWith("-") || argument == "/?" || argument == "/h") {
        String value;
        if (argument.startsWith("-D")) {
          value = argument.substring("-D".length);
          argument = "-D";
        } else {
          index = argument.indexOf("=");
          if (index != -1) {
            value = argument.substring(index + 1);
            argument = argument.substring(0, index);
          }
        }
        ValueSpecification valueSpecification = specification[argument];
        if (valueSpecification == null) {
          throw new CommandLineProblem.deprecated(
              "Unknown option '$argument'.");
        }
        String canonicalArgument = argument;
        if (valueSpecification.alias != null) {
          canonicalArgument = valueSpecification.alias;
          valueSpecification = specification[valueSpecification.alias];
        }
        if (valueSpecification == null) {
          throw new CommandLineProblem.deprecated(
              "Unknown option alias '$canonicalArgument'.");
        }
        final bool requiresValue = valueSpecification.requiresValue;
        if (requiresValue && value == null) {
          if (!iterator.moveNext()) {
            throw new CommandLineProblem(
                templateFastaCLIArgumentRequired.withArguments(argument));
          }
          value = iterator.current;
        }
        valueSpecification.processValue(
            result, canonicalArgument, argument, value);
      } else {
        result.arguments.add(argument);
      }
    }
    specification.forEach((String key, ValueSpecification value) {
      if (value.defaultValue != null) {
        result.options[key] ??= value.defaultValue;
      }
    });
    result.arguments.addAll(nonOptions);
    return result;
  }
}

// Before adding new options here, you must:
//  * Document the option.
//  * Get an explicit approval from the front-end team.
const Map<String, ValueSpecification> optionSpecification =
    const <String, ValueSpecification>{
  Flags.compileSdk: const UriValue(),
  Flags.dumpIr: const BoolValue(false),
  Flags.enableExperiment: const StringListValue(),
  Flags.excludeSource: const BoolValue(false),
  Flags.omitPlatform: const BoolValue(false),
  Flags.fatal: const StringListValue(),
  Flags.fatalSkip: const StringValue(),
  Flags.forceLateLowering: const BoolValue(false),
  Flags.forceStaticFieldLowering: const BoolValue(false),
  Flags.forceNoExplicitGetterCalls: const BoolValue(false),
  Flags.help: const BoolValue(false),
  Flags.librariesJson: const UriValue(),
  Flags.noDefines: const BoolValue(false),
  Flags.output: const UriValue(),
  Flags.packages: const UriValue(),
  Flags.platform: const UriValue(),
  Flags.sdk: const UriValue(),
  Flags.singleRootBase: const UriValue(),
  Flags.singleRootScheme: const StringValue(),
  Flags.nnbdWeakMode: const BoolValue(false),
  Flags.nnbdStrongMode: const BoolValue(false),
  Flags.nnbdAgnosticMode: const BoolValue(false),
  Flags.target: const StringValue(),
  Flags.verbose: const BoolValue(false),
  Flags.verbosity: const StringValue(),
  Flags.verify: const BoolValue(false),
  Flags.skipPlatformVerification: const BoolValue(false),
  Flags.warnOnReachabilityCheck: const BoolValue(false),
  Flags.linkDependencies: const UriListValue(),
  Flags.noDeps: const BoolValue(false),
  Flags.invocationModes: const StringValue(),
  "-D": const DefineValue(),
  "--define": const AliasValue("-D"),
  "-h": const AliasValue(Flags.help),
  "--out": const AliasValue(Flags.output),
  "-o": const AliasValue(Flags.output),
  "-t": const AliasValue(Flags.target),
  "-v": const AliasValue(Flags.verbose),
  "/?": const AliasValue(Flags.help),
  "/h": const AliasValue(Flags.help),
};

void throwCommandLineProblem(String message) {
  throw new CommandLineProblem.deprecated(message);
}

ProcessedOptions analyzeCommandLine(String programName,
    ParsedArguments parsedArguments, bool areRestArgumentsInputs) {
  final Map<String, dynamic> options = parsedArguments.options;

  final List<String> arguments = parsedArguments.arguments;

  final bool help = options[Flags.help];

  final bool verbose = options[Flags.verbose];

  if (help) {
    print(computeUsage(programName, verbose).message);
    exit(0);
  }

  if (options.containsKey(Flags.compileSdk) &&
      options.containsKey(Flags.platform)) {
    return throw new CommandLineProblem.deprecated(
        "Can't specify both '${Flags.compileSdk}' and '${Flags.platform}'.");
  }

  final String targetName = options[Flags.target] ?? "vm";

  Map<ExperimentalFlag, bool> explicitExperimentalFlags =
      parseExperimentalFlags(
          parseExperimentalArguments(options[Flags.enableExperiment]),
          onError: throwCommandLineProblem,
          onWarning: print);

  final TargetFlags flags = new TargetFlags(
      forceLateLoweringsForTesting: options[Flags.forceLateLowering]
          ? LateLowering.all
          : LateLowering.none,
      forceStaticFieldLoweringForTesting:
          options[Flags.forceStaticFieldLowering],
      forceNoExplicitGetterCallsForTesting:
          options[Flags.forceNoExplicitGetterCalls],
      enableNullSafety: isExperimentEnabled(ExperimentalFlag.nonNullable,
          explicitExperimentalFlags: explicitExperimentalFlags));

  final Target target = getTarget(targetName, flags);
  if (target == null) {
    return throw new CommandLineProblem.deprecated(
        "Target '${targetName}' not recognized. "
        "Valid targets are:\n  ${targets.keys.join("\n  ")}");
  }

  final bool noDefines = options[Flags.noDefines];

  final bool noDeps = options[Flags.noDeps];

  final bool verify = options[Flags.verify];

  final bool skipPlatformVerification = options[Flags.skipPlatformVerification];

  final bool dumpIr = options[Flags.dumpIr];

  final bool excludeSource = options[Flags.excludeSource];

  final bool omitPlatform = options[Flags.omitPlatform];

  final Uri packages = options[Flags.packages];

  final Set<String> fatal =
      new Set<String>.from(options[Flags.fatal] ?? <String>[]);

  final bool errorsAreFatal = fatal.contains("errors");

  final bool warningsAreFatal = fatal.contains("warnings");

  final int fatalSkip = int.tryParse(options[Flags.fatalSkip] ?? "0") ?? -1;

  final bool compileSdk = options.containsKey(Flags.compileSdk);

  final String singleRootScheme = options[Flags.singleRootScheme];
  final Uri singleRootBase = options[Flags.singleRootBase];

  final bool nnbdStrongMode = options[Flags.nnbdStrongMode];

  final bool nnbdWeakMode = options[Flags.nnbdWeakMode];

  final bool nnbdAgnosticMode = options[Flags.nnbdAgnosticMode];

  final NnbdMode nnbdMode = nnbdAgnosticMode
      ? NnbdMode.Agnostic
      : (nnbdStrongMode ? NnbdMode.Strong : NnbdMode.Weak);

  final bool warnOnReachabilityCheck = options[Flags.warnOnReachabilityCheck];

  final List<Uri> linkDependencies = options[Flags.linkDependencies] ?? [];

  final String invocationModes = options[Flags.invocationModes] ?? '';

  final String verbosity = options[Flags.verbosity] ?? Verbosity.defaultValue;

  if (nnbdStrongMode && nnbdWeakMode) {
    return throw new CommandLineProblem.deprecated(
        "Can't specify both '${Flags.nnbdStrongMode}' and "
        "'${Flags.nnbdWeakMode}'.");
  }

  if (nnbdStrongMode && nnbdAgnosticMode) {
    return throw new CommandLineProblem.deprecated(
        "Can't specify both '${Flags.nnbdStrongMode}' and "
        "'${Flags.nnbdAgnosticMode}'.");
  }

  if (nnbdWeakMode && nnbdAgnosticMode) {
    return throw new CommandLineProblem.deprecated(
        "Can't specify both '${Flags.nnbdWeakMode}' and "
        "'${Flags.nnbdAgnosticMode}'.");
  }

  FileSystem fileSystem = StandardFileSystem.instance;
  if (singleRootScheme != null) {
    fileSystem = new SchemeBasedFileSystem({
      'file': fileSystem,
      'data': fileSystem,
      // TODO(askesc): remove also when fixing StandardFileSystem (empty schemes
      // should have been handled elsewhere).
      '': fileSystem,
      singleRootScheme: new SingleRootFileSystem(
          singleRootScheme, singleRootBase, fileSystem),
    });
  }

  CompilerOptions compilerOptions = new CompilerOptions()
    ..compileSdk = compileSdk
    ..fileSystem = fileSystem
    ..packagesFileUri = packages
    ..target = target
    ..throwOnErrorsForDebugging = errorsAreFatal
    ..throwOnWarningsForDebugging = warningsAreFatal
    ..skipForDebugging = fatalSkip
    ..embedSourceText = !excludeSource
    ..debugDump = dumpIr
    ..omitPlatform = omitPlatform
    ..verbose = verbose
    ..verify = verify
    ..skipPlatformVerification = skipPlatformVerification
    ..explicitExperimentalFlags = explicitExperimentalFlags
    ..environmentDefines = noDefines ? null : parsedArguments.defines
    ..nnbdMode = nnbdMode
    ..additionalDills = linkDependencies
    ..emitDeps = !noDeps
    ..warnOnReachabilityCheck = warnOnReachabilityCheck
    ..invocationModes = InvocationMode.parseArguments(invocationModes)
    ..verbosity = Verbosity.parseArgument(verbosity);

  if (programName == "compile_platform") {
    if (arguments.length != 5) {
      return throw new CommandLineProblem.deprecated(
          "Expected five arguments.");
    }
    if (compileSdk) {
      return throw new CommandLineProblem.deprecated(
          "Cannot specify '${Flags.compileSdk}' option to compile_platform.");
    }
    if (options.containsKey(Flags.output)) {
      return throw new CommandLineProblem.deprecated(
          "Cannot specify '${Flags.output}' option to compile_platform.");
    }

    return new ProcessedOptions(
        options: compilerOptions
          ..sdkSummary = options[Flags.platform]
          ..librariesSpecificationUri = resolveInputUri(arguments[1])
          ..setExitCodeOnProblem = true,
        inputs: <Uri>[Uri.parse(arguments[0])],
        output: resolveInputUri(arguments[3]));
  } else if (arguments.isEmpty) {
    return throw new CommandLineProblem.deprecated("No Dart file specified.");
  }

  final Uri defaultOutput = resolveInputUri("${arguments.first}.dill");

  final Uri output = options[Flags.output] ?? defaultOutput;

  final Uri sdk = options[Flags.sdk] ?? options[Flags.compileSdk];

  final Uri librariesJson = options[Flags.librariesJson];

  final Uri platform = compileSdk
      ? null
      : (options[Flags.platform] ??
          computePlatformBinariesLocation(forceBuildDir: true)
              .resolve(computePlatformDillName(target, nnbdMode, () {
            throwCommandLineProblem(
                "Target '${target.name}' requires an explicit "
                "'${Flags.platform}' option.");
          })));
  compilerOptions
    ..sdkRoot = sdk
    ..sdkSummary = platform
    ..librariesSpecificationUri = librariesJson;

  List<Uri> inputs = <Uri>[];
  if (areRestArgumentsInputs) {
    for (String argument in arguments) {
      inputs.add(resolveInputUri(argument));
    }
  }
  return new ProcessedOptions(
      options: compilerOptions, inputs: inputs, output: output);
}

Future<T> withGlobalOptions<T>(
    String programName,
    List<String> arguments,
    bool areRestArgumentsInputs,
    Future<T> f(CompilerContext context, List<String> restArguments)) {
  ParsedArguments parsedArguments;
  ProcessedOptions options;
  CommandLineProblem problem;
  try {
    parsedArguments = ParsedArguments.parse(arguments, optionSpecification);
    options = analyzeCommandLine(
        programName, parsedArguments, areRestArgumentsInputs);
  } on CommandLineProblem catch (e) {
    options = new ProcessedOptions();
    problem = e;
  }

  return CompilerContext.runWithOptions<T>(options, (CompilerContext c) {
    if (problem != null) {
      print(computeUsage(programName, options.verbose).message);
      PlainAndColorizedString formatted =
          c.format(problem.message.withoutLocation(), Severity.error);
      String formattedText;
      if (enableColors) {
        formattedText = formatted.colorized;
      } else {
        formattedText = formatted.plain;
      }
      print(formattedText);
      exit(1);
    }

    return f(c, parsedArguments.arguments);
  }, errorOnMissingInput: problem == null);
}

Message computeUsage(String programName, bool verbose) {
  String basicUsage = "Usage: $programName [options] dartfile\n";
  String summary;
  String options =
      (verbose ? messageFastaUsageLong.message : messageFastaUsageShort.message)
          .trim();
  switch (programName) {
    case "outline":
      summary =
          "Creates an outline of a Dart program in the Dill/Kernel IR format.";
      break;

    case "compile":
      summary = "Compiles a Dart program to the Dill/Kernel IR format.";
      break;

    case "run":
      summary = "Runs a Dart program.";
      break;

    case "compile_platform":
      summary = "Compiles Dart SDK platform to the Dill/Kernel IR format.";
      basicUsage = "Usage: $programName [options]"
          " dart-library-uri libraries.json vm_outline_strong.dill"
          " platform.dill outline.dill\n";
  }
  StringBuffer sb = new StringBuffer(basicUsage);
  if (summary != null) {
    sb.writeln();
    sb.writeln(summary);
    sb.writeln();
  }
  sb.write(options);
  // TODO(ahe): Don't use [templateUnspecified].
  return templateUnspecified.withArguments("$sb");
}

Future<T> runProtectedFromAbort<T>(Future<T> Function() action,
    [T failingValue]) async {
  if (CompilerContext.isActive) {
    throw "runProtectedFromAbort should be called from 'main',"
        " that is, outside a compiler context.";
  }
  try {
    return await action();
  } on DebugAbort catch (e) {
    print(e.message.message);

    // DebugAbort should never happen in production code, so we want test.py to
    // treat this as a crash which is signalled by exiting with 255.
    exit(255);
  }
}

abstract class ValueSpecification {
  const ValueSpecification();

  String get alias => null;

  dynamic get defaultValue => null;

  bool get requiresValue => true;

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value);
}

class AliasValue extends ValueSpecification {
  final String alias;

  const AliasValue(this.alias);

  bool get requiresValue =>
      throw new UnsupportedError("AliasValue.requiresValue");

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    throw new UnsupportedError("AliasValue.processValue");
  }
}

class UriValue extends ValueSpecification {
  const UriValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    if (result.options.containsKey(canonicalArgument)) {
      throw new CommandLineProblem.deprecated(
          "Multiple values for '$argument': "
          "'${result.options[canonicalArgument]}' and '$value'.");
    }
    // TODO(ahe): resolve Uris lazily, so that schemes provided by
    // other flags can be used for parsed command-line arguments too.
    result.options[canonicalArgument] = resolveInputUri(value);
  }
}

class StringValue extends ValueSpecification {
  const StringValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    if (result.options.containsKey(canonicalArgument)) {
      throw new CommandLineProblem.deprecated(
          "Multiple values for '$argument': "
          "'${result.options[canonicalArgument]}' and '$value'.");
    }
    result.options[canonicalArgument] = value;
  }
}

class BoolValue extends ValueSpecification {
  final bool defaultValue;

  const BoolValue(this.defaultValue);

  bool get requiresValue => false;

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    if (result.options.containsKey(canonicalArgument)) {
      throw new CommandLineProblem.deprecated(
          "Multiple values for '$argument': "
          "'${result.options[canonicalArgument]}' and '$value'.");
    }
    bool parsedValue;
    if (value == null || value == "true" || value == "yes") {
      parsedValue = true;
    } else if (value == "false" || value == "no") {
      parsedValue = false;
    } else {
      throw new CommandLineProblem.deprecated(
          "Value for '$argument' is '$value', "
          "but expected one of: 'true', 'false', 'yes', or 'no'.");
    }
    result.options[canonicalArgument] = parsedValue;
  }
}

class IntValue extends ValueSpecification {
  const IntValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    if (result.options.containsKey(canonicalArgument)) {
      throw new CommandLineProblem.deprecated(
          "Multiple values for '$argument': "
          "'${result.options[canonicalArgument]}' and '$value'.");
    }
    int parsedValue = int.tryParse(value);
    if (parsedValue == null) {
      throw new CommandLineProblem.deprecated(
          "Value for '$argument', '$value', isn't an int.");
    }
    result.options[canonicalArgument] = parsedValue;
  }
}

class DefineValue extends ValueSpecification {
  const DefineValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    int index = value.indexOf('=');
    String name;
    String expression;
    if (index != -1) {
      name = value.substring(0, index);
      expression = value.substring(index + 1);
    } else {
      name = value;
      expression = value;
    }
    result.defines[name] = expression;
  }
}

class StringListValue extends ValueSpecification {
  const StringListValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    result.options
        .putIfAbsent(canonicalArgument, () => <String>[])
        .addAll(value.split(","));
  }
}

class UriListValue extends ValueSpecification {
  const UriListValue();

  void processValue(ParsedArguments result, String canonicalArgument,
      String argument, String value) {
    result.options
        .putIfAbsent(canonicalArgument, () => <Uri>[])
        .addAll(value.split(",").map(resolveInputUri));
  }
}
