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

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