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

library fasta.tool.command_line;

import 'dart:io' show exit;

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

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

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,
        templateUnspecified;

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

import 'package:_fe_analyzer_shared/src/util/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 Target, TargetFlags, TestTargetFlags, getTarget, targets;

// Before adding new options here, you must:
//  * Document the option.
//  * Get an explicit approval from the front-end team.
const List<Option> optionSpecification = [
  Options.compileSdk,
  Options.dumpIr,
  Options.enableExperiment,
  Options.enableUnscheduledExperiments,
  Options.excludeSource,
  Options.omitPlatform,
  Options.fatal,
  Options.fatalSkip,
  Options.forceLateLowering,
  Options.forceLateLoweringSentinel,
  Options.forceStaticFieldLowering,
  Options.forceNoExplicitGetterCalls,
  Options.forceConstructorTearOffLowering,
  Options.help,
  Options.librariesJson,
  Options.noDefines,
  Options.output,
  Options.packages,
  Options.platform,
  Options.sdk,
  Options.singleRootBase,
  Options.singleRootScheme,
  Options.nnbdWeakMode,
  Options.nnbdStrongMode,
  Options.nnbdAgnosticMode,
  Options.target,
  Options.verbose,
  Options.verbosity,
  Options.verify,
  Options.skipPlatformVerification,
  Options.warnOnReachabilityCheck,
  Options.linkDependencies,
  Options.noDeps,
  Options.invocationModes,
  Options.defines,
];

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

ProcessedOptions analyzeCommandLine(String programName,
    ParsedOptions parsedOptions, bool areRestArgumentsInputs) {
  final List<String> arguments = parsedOptions.arguments;

  final bool help = Options.help.read(parsedOptions);

  final bool verbose = Options.verbose.read(parsedOptions);

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

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

  final String targetName = Options.target.read(parsedOptions);

  Map<ExperimentalFlag, bool> explicitExperimentalFlags =
      parseExperimentalFlags(
          parseExperimentalArguments(
              Options.enableExperiment.read(parsedOptions)),
          onError: throwCommandLineProblem,
          onWarning: print);

  final TargetFlags flags = new TestTargetFlags(
      forceLateLoweringsForTesting:
          Options.forceLateLowering.read(parsedOptions),
      forceStaticFieldLoweringForTesting:
          Options.forceStaticFieldLowering.read(parsedOptions),
      forceNoExplicitGetterCallsForTesting:
          Options.forceNoExplicitGetterCalls.read(parsedOptions),
      forceConstructorTearOffLoweringForTesting:
          Options.forceConstructorTearOffLowering.read(parsedOptions),
      forceLateLoweringSentinelForTesting:
          Options.forceLateLoweringSentinel.read(parsedOptions),
      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.noDefines.read(parsedOptions);

  final bool noDeps = Options.noDeps.read(parsedOptions);

  final bool verify = Options.verify.read(parsedOptions);

  final bool skipPlatformVerification =
      Options.skipPlatformVerification.read(parsedOptions);

  final bool dumpIr = Options.dumpIr.read(parsedOptions);

  final bool excludeSource = Options.excludeSource.read(parsedOptions);

  final bool omitPlatform = Options.omitPlatform.read(parsedOptions);

  final Uri? packages = Options.packages.read(parsedOptions);

  final Set<String> fatal =
      new Set<String>.from(Options.fatal.read(parsedOptions) ?? <String>[]);

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

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

  final int fatalSkip =
      int.tryParse(Options.fatalSkip.read(parsedOptions) ?? "0") ?? -1;

  final bool compileSdk = Options.compileSdk.read(parsedOptions) != null;

  final String? singleRootScheme = Options.singleRootScheme.read(parsedOptions);
  final Uri? singleRootBase = Options.singleRootBase.read(parsedOptions);

  final bool nnbdStrongMode = Options.nnbdStrongMode.read(parsedOptions);

  final bool nnbdWeakMode = Options.nnbdWeakMode.read(parsedOptions);

  final bool nnbdAgnosticMode = Options.nnbdAgnosticMode.read(parsedOptions);

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

  final bool enableUnscheduledExperiments =
      Options.enableUnscheduledExperiments.read(parsedOptions);

  final bool warnOnReachabilityCheck =
      Options.warnOnReachabilityCheck.read(parsedOptions);

  final List<Uri> linkDependencies =
      Options.linkDependencies.read(parsedOptions) ?? [];

  final String invocationModes =
      Options.invocationModes.read(parsedOptions) ?? '';

  final String verbosity = Options.verbosity.read(parsedOptions);

  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),
    });
  }

  // In order to facilitate the roll out of CFE constants on Dart2js, we need to
  // be able to support both passing '--no-defines' and also evaluating CFE
  // constants when the target supports it. This is so we can easily enable or
  // disable fully evaluating constants in the CFE with a flag. This can be
  // deleted when the CFE fully evaluates constants for Dart2js in all cases.
  Map<String, String>? environmentDefines;
  if (noDefines && target.constantsBackend.supportsUnevaluatedConstants) {
    // Pass a null environment.
  } else {
    environmentDefines = parsedOptions.defines;
  }

  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 = environmentDefines
    ..nnbdMode = nnbdMode
    ..enableUnscheduledExperiments = enableUnscheduledExperiments
    ..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 (parsedOptions.options.containsKey(Flags.output)) {
      return throw new CommandLineProblem.deprecated(
          "Cannot specify '${Flags.output}' option to compile_platform.");
    }

    return new ProcessedOptions(
        options: compilerOptions
          ..sdkSummary = Options.platform.read(parsedOptions)
          ..librariesSpecificationUri = resolveInputUri(arguments[1])
          ..setExitCodeOnProblem = true,
        inputs: arguments[0].split(',').map(Uri.parse).toList(),
        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.output.read(parsedOptions) ?? defaultOutput;

  final Uri? sdk =
      Options.sdk.read(parsedOptions) ?? Options.compileSdk.read(parsedOptions);

  final Uri? librariesJson = Options.librariesJson.read(parsedOptions);

  final Uri? platform = compileSdk
      ? null
      : (Options.platform.read(parsedOptions) ??
          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)) {
  ParsedOptions? parsedOptions;
  ProcessedOptions options;
  CommandLineProblem? problem;
  try {
    parsedOptions = ParsedOptions.parse(arguments, optionSpecification);
    options =
        analyzeCommandLine(programName, parsedOptions, 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).problemMessage);
      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, parsedOptions!.arguments);
  }, errorOnMissingInput: problem == null);
}

Message computeUsage(String programName, bool verbose) {
  String basicUsage = "Usage: $programName [options] dartfile\n";
  String? summary;
  String options = (verbose
          ? messageFastaUsageLong.problemMessage
          : messageFastaUsageShort.problemMessage)
      .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.problemMessage);

    // 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);
  }
}
