// Copyright (c) 2018, 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:io';

import 'package:args/args.dart';
import 'package:front_end/src/api_unstable/ddc.dart'
    show InitializedCompilerState, parseExperimentalArguments;
import 'package:path/path.dart' as p;

import 'module_builder.dart';

// TODO(nshahan) Merge all of this file the locations where they are used in
// the kernel (only) version of DDC.

/// Previously was shared code between Analyzer and Kernel CLI interfaces.
///
/// This file should only implement functionality that does not depend on
/// Analyzer/Kernel imports.

/// Compiler options for the `dartdevc` backend.
class SharedCompilerOptions {
  /// Whether to emit the source mapping file.
  ///
  /// This supports debugging the original source code instead of the generated
  /// code.
  final bool sourceMap;

  /// Whether to emit the source mapping file in the program text, so the
  /// runtime can enable synchronous stack trace deobfuscation.
  final bool inlineSourceMap;

  /// Whether to emit the full compiled kernel.
  ///
  /// This is used by expression compiler worker, launched from the debugger
  /// in webdev and google3 scenarios, for expression evaluation features.
  /// Full kernel for compiled files is needed to be able to compile
  /// expressions on demand in the current scope of a breakpoint.
  final bool emitFullCompiledKernel;

  /// Whether to emit a summary file containing API signatures.
  ///
  /// This is required for a modular build process.
  final bool summarizeApi;

  // Whether to enable assertions.
  final bool enableAsserts;

  /// Whether to compile code in a more permissive REPL mode allowing access
  /// to private members across library boundaries.
  ///
  /// This should only set `true` by our REPL compiler.
  bool replCompile;

  /// Whether to emit the debug metadata
  ///
  /// Debugger uses this information about to construct mapping between
  /// modules and libraries that otherwise requires expensive communication with
  /// the browser.
  final bool emitDebugMetadata;

  /// Whether to emit the debug symbols
  ///
  /// Debugger uses this information about to construct mapping between
  /// dart and js objects that otherwise requires expensive communication with
  /// the browser.
  final bool emitDebugSymbols;

  final Map<String, String> summaryModules;

  final List<ModuleFormat> moduleFormats;

  /// The name of the module.
  ///
  /// This is used to support file concatenation. The JS module will contain its
  /// module name inside itself, allowing it to declare the module name
  /// independently of the file.
  final String moduleName;

  /// Custom scheme to indicate a multi-root uri.
  final String multiRootScheme;

  /// Path to set multi-root files relative to when generating source-maps.
  final String? multiRootOutputPath;

  /// Experimental language features that are enabled/disabled, see
  /// [the spec](https://github.com/dart-lang/sdk/blob/master/docs/process/experimental-flags.md)
  /// for more details.
  final Map<String, bool> experiments;

  final bool soundNullSafety;

  /// A canary feature that enables a new runtime type representation.
  final bool newRuntimeTypes;

  SharedCompilerOptions(
      {this.sourceMap = true,
      this.inlineSourceMap = false,
      this.summarizeApi = true,
      this.enableAsserts = true,
      this.replCompile = false,
      this.emitDebugMetadata = false,
      this.emitDebugSymbols = false,
      this.emitFullCompiledKernel = false,
      this.summaryModules = const {},
      this.moduleFormats = const [],
      required this.moduleName,
      this.multiRootScheme = 'org-dartlang-app',
      this.multiRootOutputPath,
      this.experiments = const {},
      this.soundNullSafety = false,
      bool canaryFeatures = false})
      : // Current canary features.
        newRuntimeTypes = canaryFeatures;

  SharedCompilerOptions.fromArguments(ArgResults args)
      : this(
            sourceMap: args['source-map'] as bool,
            inlineSourceMap: args['inline-source-map'] as bool,
            summarizeApi: args['summarize'] as bool,
            enableAsserts: args['enable-asserts'] as bool,
            replCompile: args['repl-compile'] as bool,
            emitDebugMetadata: args['experimental-emit-debug-metadata'] as bool,
            emitDebugSymbols: args['emit-debug-symbols'] as bool,
            emitFullCompiledKernel:
                args['experimental-output-compiled-kernel'] as bool,
            summaryModules:
                _parseCustomSummaryModules(args['summary'] as List<String>),
            moduleFormats: parseModuleFormatOption(args),
            moduleName: _getModuleName(args),
            multiRootScheme: args['multi-root-scheme'] as String,
            multiRootOutputPath: args['multi-root-output-path'] as String?,
            experiments: parseExperimentalArguments(
                args['enable-experiment'] as List<String>),
            soundNullSafety: args['sound-null-safety'] as bool,
            canaryFeatures: args['canary'] as bool);

  SharedCompilerOptions.fromSdkRequiredArguments(ArgResults args)
      : this(
            summarizeApi: false,
            moduleFormats: parseModuleFormatOption(args),
            // When compiling the SDK use dart_sdk as the default. This is the
            // assumed name in various places around the build systems.
            moduleName:
                args['module-name'] != null ? _getModuleName(args) : 'dart_sdk',
            multiRootScheme: args['multi-root-scheme'] as String,
            multiRootOutputPath: args['multi-root-output-path'] as String?,
            experiments: parseExperimentalArguments(
                args['enable-experiment'] as List<String>),
            soundNullSafety: args['sound-null-safety'] as bool,
            canaryFeatures: args['canary'] as bool);

  static void addArguments(ArgParser parser, {bool hide = true}) {
    addSdkRequiredArguments(parser, hide: hide);

    parser
      ..addMultiOption('summary',
          abbr: 's',
          help: 'API summary file(s) of imported libraries, optionally\n'
              'with module import path: -s path.dill=js/import/path')
      ..addFlag('summarize',
          help: 'Emit an API summary file.', defaultsTo: true, hide: hide)
      ..addFlag('source-map',
          help: 'Emit source mapping.', defaultsTo: true, hide: hide)
      ..addFlag('inline-source-map',
          help: 'Emit source mapping inline.', defaultsTo: false, hide: hide)
      ..addFlag('enable-asserts',
          help: 'Enable assertions.', defaultsTo: true, hide: hide)
      ..addFlag('repl-compile',
          help: 'Compile in a more permissive REPL mode, allowing access'
              ' to private members across library boundaries. This should'
              ' only be used by debugging tools.',
          defaultsTo: false,
          hide: hide)
      // TODO(41852) Define a process for breaking changes before graduating from
      // experimental.
      ..addFlag('experimental-emit-debug-metadata',
          help: 'Experimental option for compiler development.\n'
              'Output a metadata file for debug tools next to the .js output.',
          defaultsTo: false,
          hide: true)
      ..addFlag('emit-debug-symbols',
          help: 'Experimental option for compiler development.\n'
              'Output a symbols file for debug tools next to the .js output.',
          defaultsTo: false,
          hide: true)
      ..addFlag('experimental-output-compiled-kernel',
          help: 'Experimental option for compiler development.\n'
              'Output a full kernel file for currently compiled module next to '
              'the .js output.',
          defaultsTo: false,
          hide: true);
  }

  /// Adds only the arguments used to compile the SDK from a full dill file.
  ///
  /// NOTE: The 'module-name' option will have a special default value of
  /// 'dart_sdk' when compiling the SDK.
  /// See [SharedCompilerOptions.fromSdkRequiredArguments].
  static void addSdkRequiredArguments(ArgParser parser, {bool hide = true}) {
    addModuleFormatOptions(parser, hide: hide);
    parser
      ..addMultiOption('out', abbr: 'o', help: 'Output file (required).')
      ..addOption('module-name',
          help: 'The output module name, used in some JS module formats.\n'
              'Defaults to the output file name (without .js).')
      ..addOption('multi-root-scheme',
          help: 'The custom scheme to indicate a multi-root uri.',
          defaultsTo: 'org-dartlang-app')
      ..addOption('multi-root-output-path',
          help: 'Path to set multi-root files relative to when generating'
              ' source-maps.',
          hide: true)
      ..addMultiOption('enable-experiment',
          help: 'Enable/disable experimental language features.', hide: hide)
      ..addFlag('sound-null-safety',
          help: 'Compile for sound null safety at runtime.',
          negatable: true,
          defaultsTo: false)
      ..addFlag('canary',
          help: 'Enable all compiler features under active development. '
              'This option is intended for compiler development only. '
              'Canary features are likely to be unstable and can be removed '
              'without warning.',
          defaultsTo: false,
          hide: true);
  }

  static String _getModuleName(ArgResults args) {
    var moduleName = args['module-name'] as String?;
    if (moduleName == null) {
      var outPaths = args['out'] as List<String>;
      if (outPaths.isEmpty) {
        throw UnsupportedError(
            'No module name provided and unable to synthesize one without any '
            'output paths.');
      }
      var outPath = outPaths.first;
      moduleName = p.basenameWithoutExtension(outPath);
    }
    // TODO(jmesserly): this should probably use sourcePathToUri.
    //
    // Also we should not need this logic if the user passed in the module name
    // explicitly. It is here for backwards compatibility until we can confirm
    // that build systems do not depend on passing windows-style paths here.
    return p.toUri(moduleName).toString();
  }
}

/// Finds explicit module names of the form `path=name` in [summaryPaths],
/// and returns the path to mapping in an ordered map from `path` to `name`.
///
/// A summary path can contain "=" followed by an explicit module name to
/// allow working with summaries whose physical location is outside of the
/// module root directory.
Map<String, String> _parseCustomSummaryModules(List<String> summaryPaths,
    [String? moduleRoot, String? summaryExt]) {
  var pathToModule = <String, String>{};
  for (var summaryPath in summaryPaths) {
    var equalSign = summaryPath.indexOf('=');
    String modulePath;
    var summaryPathWithoutExt = summaryExt != null
        ? summaryPath.substring(
            0,
            // Strip off the extension, including the last `.`.
            summaryPath.length - (summaryExt.length + 1))
        : p.withoutExtension(summaryPath);
    if (equalSign != -1) {
      modulePath = summaryPath.substring(equalSign + 1);
      summaryPath = summaryPath.substring(0, equalSign);
    } else if (moduleRoot != null && p.isWithin(moduleRoot, summaryPath)) {
      // TODO(jmesserly): remove this, it's legacy --module-root support.
      modulePath = p.url.joinAll(
          p.split(p.relative(summaryPathWithoutExt, from: moduleRoot)));
    } else {
      modulePath = p.basename(summaryPathWithoutExt);
    }
    pathToModule[summaryPath] = modulePath;
  }
  return pathToModule;
}

/// Taken from analyzer to implement `--ignore-unrecognized-flags`
List<String> filterUnknownArguments(List<String> args, ArgParser parser) {
  if (!args.contains('--ignore-unrecognized-flags')) return args;

  var knownOptions = <String>{};
  var knownAbbreviations = <String>{};
  parser.options.forEach((String name, Option option) {
    knownOptions.add(name);
    var abbreviation = option.abbr;
    if (abbreviation != null) {
      knownAbbreviations.add(abbreviation);
    }
    if (option.negatable != null && option.negatable!) {
      knownOptions.add('no-$name');
    }
  });

  String optionName(int prefixLength, String arg) {
    var equalsOffset = arg.lastIndexOf('=');
    if (equalsOffset < 0) {
      return arg.substring(prefixLength);
    }
    return arg.substring(prefixLength, equalsOffset);
  }

  var filtered = <String>[];
  for (var arg in args) {
    if (arg.startsWith('--') && arg.length > 2) {
      if (knownOptions.contains(optionName(2, arg))) {
        filtered.add(arg);
      }
    } else if (arg.startsWith('-') && arg.length > 1) {
      if (knownAbbreviations.contains(optionName(1, arg))) {
        filtered.add(arg);
      }
    } else {
      filtered.add(arg);
    }
  }
  return filtered;
}

/// Convert a [source] string to a Uri, where the source may be a
/// dart/file/package URI or a local win/mac/linux path.
Uri sourcePathToUri(String source, {bool? windows}) {
  if (windows == null) {
    // Running on the web the Platform check will fail, and we can't use
    // fromEnvironment because internally it's set to true for dart.library.io.
    // So just catch the exception and if it fails then we're definitely not on
    // Windows.
    try {
      windows = Platform.isWindows;
    } catch (e) {
      windows = false;
    }
  }
  if (windows) {
    source = source.replaceAll('\\', '/');
  }

  var result = Uri.base.resolve(source);
  if (windows && result.scheme.length == 1) {
    // Assume c: or similar --- interpret as file path.
    return Uri.file(source, windows: true);
  }
  return result;
}

Uri sourcePathToRelativeUri(String source, {bool? windows}) {
  var uri = sourcePathToUri(source, windows: windows);
  if (uri.isScheme('file')) {
    var uriPath = uri.path;
    var root = Uri.base.path;
    if (uriPath.startsWith(root)) {
      return p.toUri(uriPath.substring(root.length));
    }
  }
  return uri;
}

/// Adjusts the source uris in [sourceMap] to be relative uris, and returns
/// the new map.
///
/// Source uris show up in two forms, absolute `file:` uris and custom
/// [multiRootScheme] uris (also "absolute" uris, but always relative to some
/// multi-root).
///
/// - `file:` uris are converted to be relative to [sourceMapBase], which
///   defaults to the dirname of [sourceMapPath] if not provided.
///
/// - [multiRootScheme] uris are prefixed by [multiRootOutputPath]. If the
///   path starts with `/lib`, then we strip that before making it relative
///   to the [multiRootOutputPath], and assert that [multiRootOutputPath]
///   starts with `/packages` (more explanation inline).
///
// TODO(#40251): Remove this logic from dev_compiler itself, push it to the
// invokers of dev_compiler which have more knowledge about how they want
// source paths to look.
Map placeSourceMap(Map sourceMap, String sourceMapPath, String? multiRootScheme,
    {String? multiRootOutputPath, String? sourceMapBase}) {
  var map = Map.from(sourceMap);
  // Convert to a local file path if it's not.
  sourceMapPath = sourcePathToUri(p.absolute(p.fromUri(sourceMapPath))).path;
  var sourceMapDir = p.url.dirname(sourceMapPath);
  sourceMapBase ??= sourceMapDir;
  var list = (map['sources'] as List).toList();

  String makeRelative(String sourcePath) {
    var uri = sourcePathToUri(sourcePath);
    var scheme = uri.scheme;
    if (scheme == 'dart' || scheme == 'package' || scheme == multiRootScheme) {
      if (scheme == multiRootScheme) {
        // TODO(sigmund): extract all source-map normalization outside ddc. This
        // custom logic is BUILD specific and could be shared with other tools
        // like dart2js.
        var shortPath = uri.path.replaceAll('/sdk/', '/dart-sdk/');
        var multiRootPath = "${multiRootOutputPath ?? ''}$shortPath";
        multiRootPath = p.url.relative(multiRootPath, from: sourceMapDir);
        return multiRootPath;
      }
      return sourcePath;
    }

    if (uri.isScheme('http')) return sourcePath;

    // Convert to a local file path if it's not.
    sourcePath = sourcePathToUri(p.absolute(p.fromUri(uri))).path;

    // Fall back to a relative path against the source map itself.
    sourcePath = p.url.relative(sourcePath, from: sourceMapBase);

    // Convert from relative local path to relative URI.
    return p.toUri(sourcePath).path;
  }

  for (var i = 0; i < list.length; i++) {
    list[i] = makeRelative(list[i] as String);
  }
  map['sources'] = list;
  map['file'] =
      map['file'] != null ? makeRelative(map['file'] as String) : null;
  return map;
}

/// The result of a single `dartdevc` compilation.
///
/// Typically used for exiting the process with [exitCode] or checking the
/// [success] of the compilation.
///
/// For batch/worker compilations, the [compilerState] provides an opportunity
/// to reuse state from the previous run, if the options/input summaries are
/// equivalent. Otherwise it will be discarded.
class CompilerResult {
  /// Optionally provides the front_end state from the previous compilation,
  /// which can be passed to [compile] to potentially speed up the next
  /// compilation.
  final InitializedCompilerState? kernelState;

  /// The process exit code of the compiler.
  final int exitCode;

  CompilerResult(this.exitCode, {this.kernelState});

  /// Gets the kernel compiler state, if any.
  Object? get compilerState => kernelState;

  /// Whether the program compiled without any fatal errors (equivalent to
  /// [exitCode] == 0).
  bool get success => exitCode == 0;

  /// Whether the compiler crashed (i.e. threw an unhandled exception,
  /// typically indicating an internal error in DDC itself or its front end).
  bool get crashed => exitCode == 70;
}

/// Stores the result of preprocessing `dartdevc` command line arguments.
///
/// `dartdevc` preprocesses arguments to support some features that
/// `package:args` does not handle (training `@` to reference arguments in a
/// file).
///
/// [isBatch]/[isWorker] mode are preprocessed because they can combine
/// argument lists from the initial invocation and from batch/worker jobs.
class ParsedArguments {
  /// The user's arguments to the compiler for this compilation.
  final List<String> rest;

  /// Whether to run in `--batch` mode, e.g the Dart SDK and Language tests.
  ///
  /// Similar to [isWorker] but with a different protocol.
  /// See also [isBatchOrWorker].
  final bool isBatch;

  /// Whether to run in `--experimental-expression-compiler` mode.
  ///
  /// This is a special mode that is optimized for only compiling expressions.
  ///
  /// All dependencies must come from precompiled dill files, and those must
  /// be explicitly invalidated as needed between expression compile requests.
  /// Invalidation of dill is performed using [updateDeps] from the client (i.e.
  /// debugger) and should be done every time a dill file changes, for example,
  /// on hot reload or rebuild.
  final bool isExpressionCompiler;

  /// Whether to run in `--bazel_worker` mode, e.g. for Bazel builds.
  ///
  /// Similar to [isBatch] but with a different protocol.
  /// See also [isBatchOrWorker].
  final bool isWorker;

  /// Whether to re-use the last compiler result when in a worker.
  ///
  /// This is useful if we are repeatedly compiling things in the same context,
  /// e.g. in a debugger REPL.
  final bool reuseResult;

  /// Whether to use the incremental compiler for compiling.
  ///
  /// Note that this only makes sense when also reusing results.
  final bool useIncrementalCompiler;

  ParsedArguments._(
    this.rest, {
    this.isBatch = false,
    this.isWorker = false,
    this.reuseResult = false,
    this.useIncrementalCompiler = false,
    this.isExpressionCompiler = false,
  });

  /// Preprocess arguments to determine whether DDK is used in batch mode or as a
  /// persistent worker.
  ///
  /// When used in batch mode, we expect a `--batch` parameter.
  ///
  /// When used as a persistent bazel worker, the `--persistent_worker` might be
  /// present, and an argument of the form `@path/to/file` might be provided. The
  /// latter needs to be replaced by reading all the contents of the
  /// file and expanding them into the resulting argument list.
  factory ParsedArguments.from(List<String> args) {
    if (args.isEmpty) return ParsedArguments._(args);

    var newArgs = <String>[];
    var isWorker = false;
    var isBatch = false;
    var reuseResult = false;
    var useIncrementalCompiler = false;
    var isExpressionCompiler = false;

    Iterable<String> argsToParse = args;

    // Expand `@path/to/file`
    if (args.last.startsWith('@')) {
      var extra = _readLines(args.last.substring(1));
      argsToParse = args.take(args.length - 1).followedBy(extra);
    }

    for (var arg in argsToParse) {
      if (arg == '--persistent_worker') {
        isWorker = true;
      } else if (arg == '--batch') {
        isBatch = true;
      } else if (arg == '--reuse-compiler-result') {
        reuseResult = true;
      } else if (arg == '--use-incremental-compiler') {
        useIncrementalCompiler = true;
      } else if (arg == '--experimental-expression-compiler') {
        isExpressionCompiler = true;
      } else {
        newArgs.add(arg);
      }
    }
    return ParsedArguments._(newArgs,
        isWorker: isWorker,
        isBatch: isBatch,
        reuseResult: reuseResult,
        useIncrementalCompiler: useIncrementalCompiler,
        isExpressionCompiler: isExpressionCompiler);
  }

  /// Whether the compiler is running in [isBatch] or [isWorker] mode.
  ///
  /// Both modes are generally equivalent from the compiler's perspective,
  /// the main difference is that they use distinct protocols to communicate
  /// jobs to the compiler.
  bool get isBatchOrWorker => isBatch || isWorker;

  /// Merge [args] and return the new parsed arguments.
  ///
  /// Typically used when [isBatchOrWorker] is set to merge the compilation's
  /// arguments with any global ones that were provided when the worker started.
  ParsedArguments merge(List<String> arguments) {
    // Parse the arguments again so `--kernel` can be passed. This provides
    // added safety that we are really compiling in Kernel mode, if somehow the
    // worker was not initialized correctly.
    var newArgs = ParsedArguments.from(arguments);
    if (newArgs.isBatchOrWorker) {
      throw ArgumentError('cannot change batch or worker mode after startup.');
    }
    return ParsedArguments._(rest.toList()..addAll(newArgs.rest),
        isWorker: isWorker,
        isBatch: isBatch,
        reuseResult: reuseResult || newArgs.reuseResult,
        useIncrementalCompiler:
            useIncrementalCompiler || newArgs.useIncrementalCompiler);
  }
}

/// Return all lines in a file found at [path].
Iterable<String> _readLines(String path) {
  try {
    return File(path).readAsLinesSync().where((String line) => line.isNotEmpty);
  } on FileSystemException catch (e) {
    throw Exception('Failed to read $path: $e');
  }
}
