// Copyright 2014 The Flutter 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 'dart:async';
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:package_config/package_config.dart';
import 'package:process/process.dart';
import 'package:usage/uuid/uuid.dart';

import 'artifacts.dart';
import 'base/common.dart';
import 'base/config.dart';
import 'base/file_system.dart';
import 'base/io.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'base/process.dart';
import 'base/utils.dart';
import 'build_info.dart';
import 'bundle.dart';
import 'convert.dart';

/// Opt-in changes to the dart compilers.
const kDartCompilerExperiments = <String>[];

/// The target model describes the set of core libraries that are available within
/// the SDK.
class TargetModel {
  /// Parse a [TargetModel] from a raw string.
  ///
  /// Throws an exception if passed a value other than 'flutter',
  /// 'flutter_runner', 'vm', or 'dartdevc'.
  factory TargetModel(String rawValue) {
    return switch (rawValue) {
      'flutter' => flutter,
      'flutter_runner' => flutterRunner,
      'vm' => vm,
      'dartdevc' => dartdevc,
      _ => throw Exception('Unexpected target model $rawValue'),
    };
  }

  const TargetModel._(this._value);

  /// The Flutter patched Dart SDK.
  static const flutter = TargetModel._('flutter');

  /// The Fuchsia patched SDK.
  static const flutterRunner = TargetModel._('flutter_runner');

  /// The Dart VM.
  static const vm = TargetModel._('vm');

  /// The development compiler for JavaScript.
  static const dartdevc = TargetModel._('dartdevc');

  final String _value;

  @override
  String toString() => _value;
}

class CompilerOutput {
  const CompilerOutput(
    this.outputFilename,
    this.errorCount,
    this.sources, {
    this.expressionData,
    this.errorMessage,
  });

  final String outputFilename;
  final int errorCount;
  final List<Uri> sources;

  /// This field is only non-null for expression compilation requests.
  final Uint8List? expressionData;

  /// This field is only non-null when a compilation error was encountered.
  final String? errorMessage;
}

enum StdoutState { CollectDiagnostic, CollectDependencies }

/// Handles stdin/stdout communication with the frontend server.
class StdoutHandler {
  StdoutHandler({required Logger logger, required FileSystem fileSystem})
    : _logger = logger,
      _fileSystem = fileSystem {
    reset();
  }

  final Logger _logger;
  final FileSystem _fileSystem;

  String? boundaryKey;
  StdoutState state = StdoutState.CollectDiagnostic;
  Completer<CompilerOutput?>? compilerOutput;
  final sources = <Uri>[];

  var _suppressCompilerMessages = false;
  var _expectSources = true;
  var _readFile = false;
  var _errorBuffer = StringBuffer();

  void handler(String message) {
    const kResultPrefix = 'result ';
    if (boundaryKey == null && message.startsWith(kResultPrefix)) {
      boundaryKey = message.substring(kResultPrefix.length);
      return;
    }
    final String? messageBoundaryKey = boundaryKey;
    if (messageBoundaryKey != null && message.startsWith(messageBoundaryKey)) {
      if (_expectSources) {
        if (state == StdoutState.CollectDiagnostic) {
          state = StdoutState.CollectDependencies;
          return;
        }
      }
      if (message.length <= messageBoundaryKey.length) {
        compilerOutput?.complete();
        return;
      }
      final int spaceDelimiter = message.lastIndexOf(' ');
      final String fileName = message.substring(messageBoundaryKey.length + 1, spaceDelimiter);
      final int errorCount = int.parse(message.substring(spaceDelimiter + 1).trim());
      Uint8List? expressionData;
      if (_readFile) {
        expressionData = _fileSystem.file(fileName).readAsBytesSync();
      }
      final output = CompilerOutput(
        fileName,
        errorCount,
        sources,
        expressionData: expressionData,
        errorMessage: _errorBuffer.isNotEmpty ? _errorBuffer.toString() : null,
      );
      compilerOutput?.complete(output);
      return;
    }
    switch (state) {
      case StdoutState.CollectDiagnostic when _suppressCompilerMessages:
        _logger.printTrace(message);
        _errorBuffer.writeln(message);
      case StdoutState.CollectDiagnostic:
        _logger.printError(message);
        _errorBuffer.writeln(message);
      case StdoutState.CollectDependencies:
        switch (message[0]) {
          case '+':
            sources.add(Uri.parse(message.substring(1)));
          case '-':
            sources.remove(Uri.parse(message.substring(1)));
          default:
            _logger.printTrace('Unexpected prefix for $message uri - ignoring');
        }
    }
  }

  // This is needed to get ready to process next compilation result output,
  // with its own boundary key and new completer.
  void reset({
    bool suppressCompilerMessages = false,
    bool expectSources = true,
    bool readFile = false,
  }) {
    boundaryKey = null;
    compilerOutput = Completer<CompilerOutput?>();
    _suppressCompilerMessages = suppressCompilerMessages;
    _expectSources = expectSources;
    _readFile = readFile;
    state = StdoutState.CollectDiagnostic;
    _errorBuffer = StringBuffer();
  }
}

/// List the preconfigured build options for a given build mode.
List<String> buildModeOptions(BuildMode mode, List<String> dartDefines) => switch (mode) {
  BuildMode.debug => <String>[
    // These checks allow the CLI to override the value of this define for unit
    // testing the framework.
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.profile')))
      '-Ddart.vm.profile=false',
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.product')))
      '-Ddart.vm.product=false',
    '--enable-asserts',
  ],
  BuildMode.profile => <String>[
    // These checks allow the CLI to override the value of this define for
    // benchmarks with most timeline traces disabled.
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.profile')))
      '-Ddart.vm.profile=true',
    if (!dartDefines.any((String define) => define.startsWith('dart.vm.product')))
      '-Ddart.vm.product=false',
    '--delete-tostring-package-uri=dart:ui',
    '--delete-tostring-package-uri=package:flutter',
    ...kDartCompilerExperiments,
  ],
  BuildMode.release => <String>[
    '-Ddart.vm.profile=false',
    '-Ddart.vm.product=true',
    '--delete-tostring-package-uri=dart:ui',
    '--delete-tostring-package-uri=package:flutter',
    ...kDartCompilerExperiments,
  ],
  _ => throw Exception('Unknown BuildMode: $mode'),
};

final _extraFrontEndOptionsFilterSet = <String>{
  // Don't allow for users to pass --include-unsupported-platform-library-stubs to bypass
  // unsupported library compile time errors as this flag is only safe for use by developer
  // tooling.
  '--include-unsupported-platform-library-stubs',
};

Iterable<String>? _filterExtraFrontEndOptions(List<String>? options) =>
    options?.where((e) => !_extraFrontEndOptionsFilterSet.contains(e));

/// A compiler interface for producing single (non-incremental) kernel files.
class KernelCompiler {
  KernelCompiler({
    required FileSystem fileSystem,
    required Logger logger,
    required ProcessManager processManager,
    required Artifacts artifacts,
    required List<String> fileSystemRoots,
    String? fileSystemScheme,
    @visibleForTesting StdoutHandler? stdoutHandler,
  }) : _logger = logger,
       _fileSystem = fileSystem,
       _artifacts = artifacts,
       _processManager = processManager,
       _fileSystemScheme = fileSystemScheme,
       _fileSystemRoots = fileSystemRoots,
       _stdoutHandler = stdoutHandler ?? StdoutHandler(logger: logger, fileSystem: fileSystem);

  final FileSystem _fileSystem;
  final Artifacts _artifacts;
  final ProcessManager _processManager;
  final Logger _logger;
  final String? _fileSystemScheme;
  final List<String> _fileSystemRoots;
  final StdoutHandler _stdoutHandler;

  Future<CompilerOutput?> compile({
    required String sdkRoot,
    String? mainPath,
    String? outputFilePath,
    String? depFilePath,
    TargetModel targetModel = TargetModel.flutter,
    bool linkPlatformKernelIn = false,
    bool aot = false,
    String? frontendServerStarterPath,
    List<String>? extraFrontEndOptions,
    List<String>? fileSystemRoots,
    String? fileSystemScheme,
    String? initializeFromDill,
    String? platformDill,
    Directory? buildDir,
    String? targetOS,
    bool checkDartPluginRegistry = false,
    required String? packagesPath,
    required BuildMode buildMode,
    required bool trackWidgetCreation,
    required List<String> dartDefines,
    required PackageConfig packageConfig,
    String? nativeAssets,
  }) async {
    final TargetPlatform? platform = targetModel == TargetModel.dartdevc
        ? TargetPlatform.web_javascript
        : null;
    // This is a URI, not a file path, so the forward slash is correct even on Windows.
    if (!sdkRoot.endsWith('/')) {
      sdkRoot = '$sdkRoot/';
    }
    String? mainUri;
    if (mainPath != null) {
      final File mainFile = _fileSystem.file(mainPath);
      final Uri mainFileUri = mainFile.uri;
      if (packagesPath != null) {
        mainUri = packageConfig.toPackageUri(mainFileUri)?.toString();
      }
      mainUri ??= toMultiRootPath(
        mainFileUri,
        _fileSystemScheme,
        _fileSystemRoots,
        _fileSystem.path.separator == r'\',
      );
    }
    if (outputFilePath != null && !_fileSystem.isFileSync(outputFilePath)) {
      _fileSystem.file(outputFilePath).createSync(recursive: true);
    }

    // Check if there's a Dart plugin registrant.
    // This is contained in the file `dart_plugin_registrant.dart` under `.dart_tools/flutter_build/`.
    final File? dartPluginRegistrant = checkDartPluginRegistry
        ? buildDir?.parent.childFile('dart_plugin_registrant.dart')
        : null;

    String? dartPluginRegistrantUri;
    if (dartPluginRegistrant != null && dartPluginRegistrant.existsSync()) {
      final Uri dartPluginRegistrantFileUri = dartPluginRegistrant.uri;
      dartPluginRegistrantUri =
          packageConfig.toPackageUri(dartPluginRegistrantFileUri)?.toString() ??
          toMultiRootPath(
            dartPluginRegistrantFileUri,
            _fileSystemScheme,
            _fileSystemRoots,
            _fileSystem.path.separator == r'\',
          );
    }

    final List<String> commandToStartFrontendServer;
    if (frontendServerStarterPath != null && frontendServerStarterPath.isNotEmpty) {
      final String engineDartPath = _artifacts.getArtifactPath(
        Artifact.engineDartBinary,
        platform: platform,
      );
      if (!_processManager.canRun(engineDartPath)) {
        throwToolExit('Unable to find Dart binary at $engineDartPath');
      }
      commandToStartFrontendServer = <String>[engineDartPath, frontendServerStarterPath];
    } else {
      final String engineDartAotRuntimePath = _artifacts.getArtifactPath(
        Artifact.engineDartAotRuntime,
        platform: platform,
      );
      if (!_processManager.canRun(engineDartAotRuntimePath)) {
        throwToolExit('Unable to find dartaotruntime binary at $engineDartAotRuntimePath');
      }
      commandToStartFrontendServer = <String>[
        engineDartAotRuntimePath,
        _artifacts.getArtifactPath(
          Artifact.frontendServerSnapshotForEngineDartSdk,
          platform: platform,
        ),
      ];
    }

    final List<String> command =
        commandToStartFrontendServer +
        <String>[
          '--sdk-root',
          sdkRoot,
          '--target=$targetModel',
          '--no-print-incremental-dependencies',
          for (final Object dartDefine in dartDefines) '-D$dartDefine',
          ...buildModeOptions(buildMode, dartDefines),
          if (trackWidgetCreation) '--track-widget-creation',
          if (!linkPlatformKernelIn) '--no-link-platform',
          if (aot) ...<String>[
            '--aot',
            '--tfa',
            // The --target-os flag only makes sense for whole program compilation.
            if (targetOS != null) ...<String>['--target-os', targetOS],
          ],
          if (packagesPath != null) ...<String>['--packages', packagesPath],
          if (outputFilePath != null) ...<String>['--output-dill', outputFilePath],
          if (depFilePath != null &&
              (fileSystemRoots == null || fileSystemRoots.isEmpty)) ...<String>[
            '--depfile',
            depFilePath,
          ],
          if (fileSystemRoots != null)
            for (final String root in fileSystemRoots) ...<String>['--filesystem-root', root],
          if (fileSystemScheme != null) ...<String>['--filesystem-scheme', fileSystemScheme],
          if (initializeFromDill != null) ...<String>[
            '--incremental',
            '--initialize-from-dill',
            initializeFromDill,
          ],
          if (platformDill != null) ...<String>['--platform', platformDill],
          if (dartPluginRegistrantUri != null) ...<String>[
            '--source',
            dartPluginRegistrantUri,
            '--source',
            'package:flutter/src/dart_plugin_registrant.dart',
            '-Dflutter.dart_plugin_registrant=$dartPluginRegistrantUri',
          ],
          if (nativeAssets != null) ...<String>['--native-assets', nativeAssets],
          // See: https://github.com/flutter/flutter/issues/103994
          '--verbosity=error',
          ...?_filterExtraFrontEndOptions(extraFrontEndOptions),
          mainUri ?? '--native-assets-only',
        ];

    _logger.printTrace(command.join(' '));
    final Process server = await _processManager.start(command);

    server.stderr.transform<String>(utf8.decoder).listen(_logger.printError);
    server.stdout.transform(utf8LineDecoder).listen(_stdoutHandler.handler);
    final int exitCode = await server.exitCode;
    if (exitCode == 0) {
      return _stdoutHandler.compilerOutput?.future;
    }
    return null;
  }
}

/// Class that allows to serialize compilation requests to the compiler.
abstract class _CompilationRequest {
  _CompilationRequest(this.completer);

  Completer<CompilerOutput?> completer;

  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler);

  Future<void> run(DefaultResidentCompiler compiler) async {
    completer.complete(await _run(compiler));
  }
}

class _RecompileRequest extends _CompilationRequest {
  _RecompileRequest(
    super.completer,
    this.mainUri,
    this.invalidatedFiles,
    this.outputPath,
    this.packageConfig,
    this.suppressErrors, {
    this.additionalSourceUri,
    this.nativeAssetsYamlUri,
    required this.recompileRestart,
  });

  Uri mainUri;
  List<Uri>? invalidatedFiles;
  String outputPath;
  PackageConfig packageConfig;
  bool suppressErrors;
  final Uri? additionalSourceUri;
  final Uri? nativeAssetsYamlUri;
  final bool recompileRestart;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async => compiler._recompile(this);
}

class _CompileExpressionRequest extends _CompilationRequest {
  _CompileExpressionRequest(
    super.completer,
    this.expression,
    this.definitions,
    this.definitionTypes,
    this.typeDefinitions,
    this.typeBounds,
    this.typeDefaults,
    this.libraryUri,
    this.klass,
    this.method,
    this.isStatic,
  );

  String expression;
  List<String>? definitions;
  List<String>? definitionTypes;
  List<String>? typeDefinitions;
  List<String>? typeBounds;
  List<String>? typeDefaults;
  String? libraryUri;
  String? klass;
  String? method;
  bool isStatic;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
      compiler._compileExpression(this);
}

class _CompileExpressionToJsRequest extends _CompilationRequest {
  _CompileExpressionToJsRequest(
    super.completer,
    this.libraryUri,
    this.scriptUri,
    this.line,
    this.column,
    this.jsModules,
    this.jsFrameValues,
    this.moduleName,
    this.expression,
  );

  final String? libraryUri;
  final String? scriptUri;
  final int line;
  final int column;
  final Map<String, String>? jsModules;
  final Map<String, String>? jsFrameValues;
  final String? moduleName;
  final String? expression;

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async =>
      compiler._compileExpressionToJs(this);
}

class _RejectRequest extends _CompilationRequest {
  _RejectRequest(super.completer);

  @override
  Future<CompilerOutput?> _run(DefaultResidentCompiler compiler) async => compiler._reject();
}

/// Wrapper around incremental frontend server compiler, that communicates with
/// server via stdin/stdout.
///
/// The wrapper is intended to stay resident in memory as user changes, reloads,
/// restarts the Flutter app.
abstract interface class ResidentCompiler {
  factory ResidentCompiler({
    required TargetPlatform targetPlatform,
    required BuildInfo buildInfo,
    required Logger logger,
    required ProcessManager processManager,
    required Artifacts artifacts,
    required Platform platform,
    required FileSystem fileSystem,
    required ShutdownHooks shutdownHooks,
    required Config config,
    bool testCompilation = false,
    TargetModel? targetModelOverride,
  }) {
    String sdkRoot = artifacts.getArtifactPath(
      Artifact.flutterPatchedSdkPath,
      platform: targetPlatform,
      mode: buildInfo.mode,
    );
    String? platformDillPath;
    String? librariesSpec;
    TargetModel targetModel = targetModelOverride ?? .flutter;

    // Configure the compiler to target the DDC runtime.
    if (targetPlatform case .web_javascript) {
      sdkRoot = artifacts.getHostArtifact(HostArtifact.flutterWebSdk).path;
      targetModel = .dartdevc;

      const platformDillName = 'ddc_outline.dill';
      platformDillPath = fileSystem
          .file(
            fileSystem.path.join(
              artifacts.getHostArtifact(.webPlatformKernelFolder).path,
              platformDillName,
            ),
          )
          .absolute
          .uri
          .toString();

      librariesSpec = fileSystem
          .file(artifacts.getHostArtifact(.flutterWebLibrariesJson))
          .uri
          .toString();

      buildInfo = buildInfo.copyWith(
        // Override the filesystem scheme so that the frontend_server can find
        // the generated entrypoint code.
        fileSystemScheme: 'org-dartlang-app',
        extraFrontEndOptions: [
          ...buildInfo.extraFrontEndOptions,
          if (buildInfo.webEnableHotReload)
          // These flags are only valid to be passed when compiling with DDC.
          ...<String>['--dartdevc-canary', '--dartdevc-module-format=ddc'],
        ],
      );
    } else {
      if (targetPlatform case .fuchsia_arm64 || .fuchsia_x64) {
        targetModel = .flutterRunner;
      }
      buildInfo = buildInfo.copyWith(
        extraFrontEndOptions: [
          ...buildInfo.extraFrontEndOptions,
          '--enable-experiment=alternative-invalidation-strategy',
        ],
      );
    }

    return DefaultResidentCompiler(
      sdkRoot,
      buildInfo: buildInfo,
      logger: logger,
      processManager: processManager,
      artifacts: artifacts,
      platform: platform,
      fileSystem: fileSystem,
      shutdownHooks: shutdownHooks,
      config: config,
      targetModel: targetModel,
      platformDill: platformDillPath,
      librariesSpec: librariesSpec,
      testCompilation: testCompilation,
    );
  }

  // TODO(zanderso): find a better way to configure additional file system
  // roots from the runner.
  // See: https://github.com/flutter/flutter/issues/50494
  void addFileSystemRoot(String root);

  /// If invoked for the first time, it compiles the Dart script identified by
  /// [mainUri], [invalidatedFiles] list is ignored.
  /// On successive runs [invalidatedFiles] indicates which files need to be
  /// recompiled.
  ///
  /// Binary file name is returned if compilation was successful, otherwise
  /// null is returned.
  ///
  /// If [checkDartPluginRegistry] is true, it is the caller's responsibility
  /// to ensure that the generated registrant file has been updated such that
  /// it is wrapping [mainUri].
  ///
  /// If [recompileRestart] is true, uses the `recompile-restart` instruction
  /// intended for a hot restart instead.
  Future<CompilerOutput?> recompile(
    Uri mainUri,
    List<Uri>? invalidatedFiles, {
    required String outputPath,
    required PackageConfig packageConfig,
    required FileSystem fs,
    String? projectRootPath,
    bool suppressErrors = false,
    bool checkDartPluginRegistry = false,
    File? dartPluginRegistrant,
    Uri? nativeAssetsYaml,
    bool recompileRestart = false,
  });

  Future<CompilerOutput?> compileExpression(
    String expression,
    List<String>? definitions,
    List<String>? definitionTypes,
    List<String>? typeDefinitions,
    List<String>? typeBounds,
    List<String>? typeDefaults,
    String? libraryUri,
    String? klass,
    String? method,
    bool isStatic,
  );

  /// Compiles [expression] in [libraryUri] at [line]:[column] to JavaScript
  /// in [moduleName].
  ///
  /// Values listed in [jsFrameValues] are substituted for their names in the
  /// [expression].
  ///
  /// Ensures that all [jsModules] are loaded and accessible inside the
  /// expression.
  ///
  /// Example values of parameters:
  /// [moduleName] is of the form '/packages/hello_world_main.dart'
  /// [jsFrameValues] is a map from js variable name to its primitive value
  /// or another variable name, for example
  /// { 'x': '1', 'y': 'y', 'o': 'null' }
  /// [jsModules] is a map from variable name to the module name, where
  /// variable name is the name originally used in JavaScript to contain the
  /// module object, for example:
  /// { 'dart':'dart_sdk', 'main': '/packages/hello_world_main.dart' }
  /// Returns a [CompilerOutput] including the name of the file containing the
  /// compilation result and a number of errors.
  Future<CompilerOutput?> compileExpressionToJs(
    String libraryUri,
    String scriptUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  );

  /// Should be invoked when results of compilation are accepted by the client.
  ///
  /// Either [accept] or [reject] should be called after every [recompile] call.
  void accept();

  /// Should be invoked when results of compilation are rejected by the client.
  ///
  /// Either [accept] or [reject] should be called after every [recompile] call.
  Future<CompilerOutput?> reject();

  /// Should be invoked when frontend server compiler should forget what was
  /// accepted previously so that next call to [recompile] produces complete
  /// kernel file.
  void reset();

  Future<Object> shutdown();
}

@visibleForTesting
class DefaultResidentCompiler implements ResidentCompiler {
  DefaultResidentCompiler(
    String sdkRoot, {
    required BuildInfo buildInfo,
    required Logger logger,
    required ProcessManager processManager,
    required this.artifacts,
    required Platform platform,
    required FileSystem fileSystem,
    required ShutdownHooks shutdownHooks,
    required Config config,
    this.testCompilation = false,
    this.targetModel = TargetModel.flutter,
    this.platformDill,
    this.librariesSpec,
    @visibleForTesting StdoutHandler? stdoutHandler,
  }) : buildMode = buildInfo.mode,
       trackWidgetCreation = buildInfo.trackWidgetCreation,
       includeUnsupportedPlatformLibraryStubs = buildInfo.includeUnsupportedPlatformLibraryStubs,
       packagesPath = buildInfo.packageConfigPath,
       initializeFromDill =
           buildInfo.initializeFromDill ??
           getDefaultCachedKernelPath(
             config: config,
             fileSystem: fileSystem,
             trackWidgetCreation: buildInfo.trackWidgetCreation,
             dartDefines: buildInfo.dartDefines,
             extraFrontEndOptions: buildInfo.extraFrontEndOptions,
           ),
       extraFrontEndOptions = buildInfo.extraFrontEndOptions,
       fileSystemScheme = buildInfo.fileSystemScheme,
       assumeInitializeFromDillUpToDate = buildInfo.assumeInitializeFromDillUpToDate,
       frontendServerStarterPath = buildInfo.frontendServerStarterPath,
       _logger = logger,
       _processManager = processManager,
       _shutdownHooks = shutdownHooks,
       _stdoutHandler = stdoutHandler ?? StdoutHandler(logger: logger, fileSystem: fileSystem),
       _platform = platform,
       dartDefines = buildInfo.dartDefines,
       // This is a URI, not a file path, so the forward slash is correct even on Windows.
       sdkRoot = sdkRoot.endsWith('/') ? sdkRoot : '$sdkRoot/',
       // Make a copy, we might need to modify it later.
       fileSystemRoots = List<String>.from(buildInfo.fileSystemRoots) {
    // Currently, the only developer tooling that requires support for importing unsupported
    // platform libraries at compile time is the widget previewer. Only developer tooling use cases
    // should support this, so this is restricted to the widget previewer's runtime target for now.
    if (includeUnsupportedPlatformLibraryStubs && targetModel != TargetModel.dartdevc) {
      throw StateError(
        'includeUnsupportedPlatformLibraryStubs should only be used by the widget-preview '
        'command.',
      );
    }
  }

  final Logger _logger;
  final ProcessManager _processManager;
  final Artifacts artifacts;
  final Platform _platform;
  final ShutdownHooks _shutdownHooks;

  final bool testCompilation;
  final BuildMode buildMode;
  final bool trackWidgetCreation;
  final bool includeUnsupportedPlatformLibraryStubs;
  final String? packagesPath;
  final TargetModel targetModel;
  final List<String> fileSystemRoots;
  final String? fileSystemScheme;
  final String? initializeFromDill;
  final bool assumeInitializeFromDillUpToDate;
  final String? frontendServerStarterPath;
  final List<String>? extraFrontEndOptions;
  final List<String> dartDefines;
  final String? librariesSpec;

  @override
  void addFileSystemRoot(String root) {
    fileSystemRoots.add(root);
  }

  /// The path to the root of the Dart SDK used to compile.
  ///
  /// This is used to resolve the [platformDill].
  final String sdkRoot;

  /// The path to the platform dill file.
  ///
  /// This does not need to be provided for the normal Flutter workflow.
  final String? platformDill;

  Process? _server;
  final StdoutHandler _stdoutHandler;
  var _compileRequestNeedsConfirmation = false;

  final _controller = StreamController<_CompilationRequest>();

  @override
  Future<CompilerOutput?> recompile(
    Uri mainUri,
    List<Uri>? invalidatedFiles, {
    required String outputPath,
    required PackageConfig packageConfig,
    bool suppressErrors = false,
    bool checkDartPluginRegistry = false,
    File? dartPluginRegistrant,
    String? projectRootPath,
    FileSystem? fs,
    Uri? nativeAssetsYaml,
    bool recompileRestart = false,
  }) async {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }
    Uri? additionalSourceUri;
    // `dart_plugin_registrant.dart` contains the Dart plugin registry.
    if (checkDartPluginRegistry &&
        dartPluginRegistrant != null &&
        dartPluginRegistrant.existsSync()) {
      additionalSourceUri = dartPluginRegistrant.uri;
    }
    final completer = Completer<CompilerOutput?>();
    _controller.add(
      _RecompileRequest(
        completer,
        mainUri,
        invalidatedFiles,
        outputPath,
        packageConfig,
        suppressErrors,
        additionalSourceUri: additionalSourceUri,
        nativeAssetsYamlUri: nativeAssetsYaml,
        recompileRestart: recompileRestart,
      ),
    );
    return completer.future;
  }

  Future<CompilerOutput?> _recompile(_RecompileRequest request) async {
    _stdoutHandler.reset();
    _compileRequestNeedsConfirmation = true;
    _stdoutHandler._suppressCompilerMessages = request.suppressErrors;

    final String mainUri =
        request.packageConfig.toPackageUri(request.mainUri)?.toString() ??
        toMultiRootPath(request.mainUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);

    String? additionalSourceUri;
    if (request.additionalSourceUri != null) {
      additionalSourceUri =
          request.packageConfig.toPackageUri(request.additionalSourceUri!)?.toString() ??
          toMultiRootPath(
            request.additionalSourceUri!,
            fileSystemScheme,
            fileSystemRoots,
            _platform.isWindows,
          );
    }

    final nativeAssets = request.nativeAssetsYamlUri?.toString();
    final Process? server = _server;
    if (server == null) {
      return _compile(
        mainUri,
        request.outputPath,
        additionalSourceUri: additionalSourceUri,
        nativeAssetsUri: nativeAssets,
      );
    }
    final String inputKey = Uuid().generateV4();

    if (nativeAssets != null && nativeAssets.isNotEmpty) {
      server.stdin.writeln('native-assets $nativeAssets');
      _logger.printTrace('<- native-assets $nativeAssets');
    }
    if (request.recompileRestart) {
      server.stdin.writeln('recompile-restart $mainUri $inputKey');
    } else {
      server.stdin.writeln('recompile $mainUri $inputKey');
    }
    _logger.printTrace('<- recompile $mainUri $inputKey');
    final List<Uri>? invalidatedFiles = request.invalidatedFiles;
    if (invalidatedFiles != null) {
      for (final Uri fileUri in invalidatedFiles) {
        String message;
        if (fileUri.scheme == 'package') {
          message = fileUri.toString();
        } else {
          message =
              request.packageConfig.toPackageUri(fileUri)?.toString() ??
              toMultiRootPath(fileUri, fileSystemScheme, fileSystemRoots, _platform.isWindows);
        }
        server.stdin.writeln(message);
        _logger.printTrace(message);
      }
    }
    server.stdin.writeln(inputKey);
    _logger.printTrace('<- $inputKey');

    return _stdoutHandler.compilerOutput?.future;
  }

  final _compilationQueue = <_CompilationRequest>[];

  Future<void> _handleCompilationRequest(_CompilationRequest request) async {
    final bool isEmpty = _compilationQueue.isEmpty;
    _compilationQueue.add(request);
    // Only trigger processing if queue was empty - i.e. no other requests
    // are currently being processed. This effectively enforces "one
    // compilation request at a time".
    if (isEmpty) {
      while (_compilationQueue.isNotEmpty) {
        final _CompilationRequest request = _compilationQueue.first;
        await request.run(this);
        _compilationQueue.removeAt(0);
      }
    }
  }

  Future<CompilerOutput?> _compile(
    String scriptUri,
    String? outputPath, {
    String? additionalSourceUri,
    String? nativeAssetsUri,
  }) async {
    final TargetPlatform? platform = (targetModel == TargetModel.dartdevc)
        ? TargetPlatform.web_javascript
        : null;
    late final List<String> commandToStartFrontendServer;
    if (frontendServerStarterPath != null && frontendServerStarterPath!.isNotEmpty) {
      commandToStartFrontendServer = <String>[
        artifacts.getArtifactPath(Artifact.engineDartBinary, platform: platform),
        frontendServerStarterPath!,
      ];
    } else {
      commandToStartFrontendServer = <String>[
        artifacts.getArtifactPath(Artifact.engineDartAotRuntime, platform: platform),
        artifacts.getArtifactPath(
          Artifact.frontendServerSnapshotForEngineDartSdk,
          platform: platform,
        ),
      ];
    }

    final command = <String>[
      ...commandToStartFrontendServer,
      '--sdk-root',
      sdkRoot,
      '--incremental',
      if (testCompilation) '--no-print-incremental-dependencies',
      '--target=$targetModel',
      // TODO(annagrin): remove once this becomes the default behavior
      // in the frontend_server.
      // https://github.com/flutter/flutter/issues/59902
      '--experimental-emit-debug-metadata',
      for (final Object dartDefine in dartDefines) '-D$dartDefine',
      if (outputPath != null) ...<String>['--output-dill', outputPath],
      // If we have a platform dill, we don't need to pass the libraries spec,
      // since the information is embedded in the .dill file.
      if (librariesSpec != null && platformDill == null) ...<String>[
        '--libraries-spec',
        librariesSpec!,
      ],
      if (packagesPath != null) ...<String>['--packages', packagesPath!],
      ...buildModeOptions(buildMode, dartDefines),
      if (trackWidgetCreation) '--track-widget-creation',
      if (includeUnsupportedPlatformLibraryStubs) '--include-unsupported-platform-library-stubs',
      for (final String root in fileSystemRoots) ...<String>['--filesystem-root', root],
      if (fileSystemScheme != null) ...<String>['--filesystem-scheme', fileSystemScheme!],
      if (initializeFromDill != null) ...<String>['--initialize-from-dill', initializeFromDill!],
      if (assumeInitializeFromDillUpToDate) '--assume-initialize-from-dill-up-to-date',
      if (additionalSourceUri != null) ...<String>[
        '--source',
        additionalSourceUri,
        '--source',
        'package:flutter/src/dart_plugin_registrant.dart',
        '-Dflutter.dart_plugin_registrant=$additionalSourceUri',
      ],
      if (nativeAssetsUri != null) ...<String>['--native-assets', nativeAssetsUri],
      if (platformDill != null) ...<String>['--platform', platformDill!],
      // See: https://github.com/flutter/flutter/issues/103994
      '--verbosity=error',
      ...?_filterExtraFrontEndOptions(extraFrontEndOptions),
    ];
    _logger.printTrace(command.join(' '));
    _server = await _processManager.start(command);
    _server?.stdout
        .transform(utf8LineDecoder)
        .listen(
          _stdoutHandler.handler,
          onDone: () {
            // when outputFilename future is not completed, but stdout is closed
            // process has died unexpectedly.
            if (_stdoutHandler.compilerOutput?.isCompleted == false) {
              _stdoutHandler.compilerOutput?.complete();
              throwToolExit('The Dart compiler exited unexpectedly.');
            }
          },
        );

    _server?.stderr.transform(utf8LineDecoder).listen(_logger.printError);

    unawaited(
      _server?.exitCode.then((int code) {
        // The frontend server exits with a 253 error code when we shutdown due to a signal.
        // Don't treat this as an error if we're in the middle of the shutdown sequence.
        if (code != 0 && !_shutdownHooks.isShuttingDown) {
          throwToolExit('The Dart compiler exited unexpectedly.');
        }
      }),
    );

    if (nativeAssetsUri != null && nativeAssetsUri.isNotEmpty) {
      _server?.stdin.writeln('native-assets $nativeAssetsUri');
      _logger.printTrace('<- native-assets $nativeAssetsUri');
    }

    _server?.stdin.writeln('compile $scriptUri');
    _logger.printTrace('<- compile $scriptUri');

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  Future<CompilerOutput?> compileExpression(
    String expression,
    List<String>? definitions,
    List<String>? definitionTypes,
    List<String>? typeDefinitions,
    List<String>? typeBounds,
    List<String>? typeDefaults,
    String? libraryUri,
    String? klass,
    String? method,
    bool isStatic,
  ) async {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    final request = _CompileExpressionRequest(
      completer,
      expression,
      definitions,
      definitionTypes,
      typeDefinitions,
      typeBounds,
      typeDefaults,
      libraryUri,
      klass,
      method,
      isStatic,
    );
    _controller.add(request);
    return completer.future;
  }

  Future<CompilerOutput?> _compileExpression(_CompileExpressionRequest request) async {
    _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false, readFile: true);

    // 'compile-expression' should be invoked after compiler has been started,
    // program was compiled.
    final Process? server = _server;
    if (server == null) {
      return null;
    }

    final String inputKey = Uuid().generateV4();
    server.stdin
      ..writeln('compile-expression $inputKey')
      ..writeln(request.expression);
    request.definitions?.forEach(server.stdin.writeln);
    server.stdin.writeln(inputKey);
    request.definitionTypes?.forEach(server.stdin.writeln);
    server.stdin.writeln(inputKey);
    request.typeDefinitions?.forEach(server.stdin.writeln);
    server.stdin.writeln(inputKey);
    request.typeBounds?.forEach(server.stdin.writeln);
    server.stdin.writeln(inputKey);
    request.typeDefaults?.forEach(server.stdin.writeln);
    server.stdin
      ..writeln(inputKey)
      ..writeln(request.libraryUri ?? '')
      ..writeln(request.klass ?? '')
      ..writeln(request.method ?? '')
      ..writeln(request.isStatic);

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  Future<CompilerOutput?> compileExpressionToJs(
    String libraryUri,
    String scriptUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  ) {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    _controller.add(
      _CompileExpressionToJsRequest(
        completer,
        libraryUri,
        scriptUri,
        line,
        column,
        jsModules,
        jsFrameValues,
        moduleName,
        expression,
      ),
    );
    return completer.future;
  }

  Future<CompilerOutput?> _compileExpressionToJs(_CompileExpressionToJsRequest request) async {
    _stdoutHandler.reset(suppressCompilerMessages: true, expectSources: false);

    // 'compile-expression-to-js' should be invoked after compiler has been started,
    // program was compiled.
    final Process? server = _server;
    if (server == null) {
      return null;
    }

    server.stdin
      ..writeln('JSON_INPUT')
      ..writeln(
        json.encode({
          'type': 'COMPILE_EXPRESSION_JS',
          'data': {
            'expression': request.expression,
            'libraryUri': request.libraryUri,
            'scriptUri': request.scriptUri,
            'line': request.line,
            'column': request.column,
            'jsModules': request.jsModules,
            'jsFrameValues': request.jsFrameValues,
            'moduleName': request.moduleName,
          },
        }),
      );

    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  void accept() {
    if (_compileRequestNeedsConfirmation) {
      _server?.stdin.writeln('accept');
      _logger.printTrace('<- accept');
    }
    _compileRequestNeedsConfirmation = false;
  }

  @override
  Future<CompilerOutput?> reject() {
    if (!_controller.hasListener) {
      _controller.stream.listen(_handleCompilationRequest);
    }

    final completer = Completer<CompilerOutput?>();
    _controller.add(_RejectRequest(completer));
    return completer.future;
  }

  Future<CompilerOutput?> _reject() async {
    if (!_compileRequestNeedsConfirmation) {
      return Future<CompilerOutput?>.value();
    }
    _stdoutHandler.reset(expectSources: false);
    _server?.stdin.writeln('reject');
    _logger.printTrace('<- reject');
    _compileRequestNeedsConfirmation = false;
    return _stdoutHandler.compilerOutput?.future;
  }

  @override
  void reset() {
    _server?.stdin.writeln('reset');
    _logger.printTrace('<- reset');
  }

  @override
  Future<Object> shutdown() async {
    // Server was never successfully created.
    final Process? server = _server;
    if (server == null) {
      return 0;
    }
    _logger.printTrace('killing pid ${server.pid}');
    server.kill();
    return server.exitCode;
  }
}

/// Convert a file URI into a multi-root scheme URI if provided, otherwise
/// return unmodified.
@visibleForTesting
String toMultiRootPath(Uri fileUri, String? scheme, List<String> fileSystemRoots, bool windows) {
  if (scheme == null || fileSystemRoots.isEmpty || fileUri.scheme != 'file') {
    return fileUri.toString();
  }
  final String filePath = fileUri.toFilePath(windows: windows);
  for (final fileSystemRoot in fileSystemRoots) {
    if (filePath.startsWith(fileSystemRoot)) {
      return '$scheme://${filePath.substring(fileSystemRoot.length)}';
    }
  }
  return fileUri.toString();
}
