// 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:archive/archive.dart';
import 'package:build_daemon/client.dart';
import 'package:build_daemon/constants.dart' as daemon;
import 'package:build_daemon/data/build_status.dart';
import 'package:build_daemon/data/build_target.dart';
import 'package:build_daemon/data/server_log.dart';
import 'package:dwds/asset_handler.dart';
import 'package:dwds/dwds.dart';
import 'package:http_multi_server/http_multi_server.dart';
import 'package:meta/meta.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_proxy/shelf_proxy.dart';
import 'package:mime/mime.dart' as mime;

import '../artifacts.dart';
import '../asset.dart';
import '../base/common.dart';
import '../base/context.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/net.dart';
import '../base/os.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../cache.dart';
import '../dart/package_map.dart';
import '../dart/pub.dart';
import '../globals.dart';
import '../platform_plugins.dart';
import '../plugins.dart';
import '../project.dart';
import '../web/chrome.dart';
import '../web/compile.dart';

/// The name of the built web project.
const String kBuildTargetName = 'web';

/// A factory for creating a [Dwds] instance.
DwdsFactory get dwdsFactory => context.get<DwdsFactory>() ?? Dwds.start;

/// The [BuildDaemonCreator] instance.
BuildDaemonCreator get buildDaemonCreator => context.get<BuildDaemonCreator>() ?? const BuildDaemonCreator();

/// A factory for creating a [WebFs] instance.
WebFsFactory get webFsFactory => context.get<WebFsFactory>() ?? WebFs.start;

/// A factory for creating an [HttpMultiServer] instance.
HttpMultiServerFactory get httpMultiServerFactory => context.get<HttpMultiServerFactory>() ?? HttpMultiServer.bind;

/// A function with the same signature as [HttpMultiServer.bind].
typedef HttpMultiServerFactory = Future<HttpServer> Function(dynamic address, int port);

/// A function with the same signature as [Dwds.start].
typedef DwdsFactory = Future<Dwds> Function({
  @required AssetHandler assetHandler,
  @required Stream<BuildResult> buildResults,
  @required ConnectionProvider chromeConnection,
  String hostname,
  ReloadConfiguration reloadConfiguration,
  bool serveDevTools,
  LogWriter logWriter,
  bool verbose,
  bool enableDebugExtension,
  UrlEncoder urlEncoder,
});

/// A function with the same signature as [WebFs.start].
typedef WebFsFactory = Future<WebFs> Function({
  @required String target,
  @required FlutterProject flutterProject,
  @required BuildInfo buildInfo,
  @required bool skipDwds,
  @required bool initializePlatform,
  @required String hostname,
  @required String port,
  @required UrlTunneller urlTunneller,
  @required List<String> dartDefines,
});

/// The dev filesystem responsible for building and serving  web applications.
class WebFs {
  @visibleForTesting
  WebFs(
    this._client,
    this._server,
    this._dwds,
    this.uri,
    this._assetServer,
    this._useBuildRunner,
    this._flutterProject,
    this._target,
    this._buildInfo,
    this._initializePlatform,
    this._dartDefines,
  );

  /// The server URL.
  final String uri;

  final HttpServer _server;
  final Dwds _dwds;
  final BuildDaemonClient _client;
  final AssetServer _assetServer;
  final bool _useBuildRunner;
  final FlutterProject _flutterProject;
  final String _target;
  final BuildInfo _buildInfo;
  final bool _initializePlatform;
  final List<String> _dartDefines;
  StreamSubscription<void> _connectedApps;

  static const String _kHostName = 'localhost';

  Future<void> stop() async {
    await _client?.close();
    await _dwds?.stop();
    await _server.close(force: true);
    await _connectedApps?.cancel();
    _assetServer?.dispose();
  }

  Future<DebugConnection> _cachedExtensionFuture;

  /// Connect and retrieve the [DebugConnection] for the current application.
  ///
  /// Only calls [AppConnection.runMain] on the subsequent connections.
  Future<ConnectionResult> connect(bool useDebugExtension) {
    final Completer<ConnectionResult> firstConnection = Completer<ConnectionResult>();
    _connectedApps = _dwds.connectedApps.listen((AppConnection appConnection) async {
      final DebugConnection debugConnection = useDebugExtension
        ? await (_cachedExtensionFuture ??= _dwds.extensionDebugConnections.stream.first)
        : await _dwds.debugConnection(appConnection);
      if (!firstConnection.isCompleted) {
        firstConnection.complete(ConnectionResult(appConnection, debugConnection));
      } else {
        appConnection.runMain();
      }
    });
    return firstConnection.future;
  }

  /// Recompile the web application and return whether this was successful.
  Future<bool> recompile() async {
    if (!_useBuildRunner) {
      await buildWeb(_flutterProject, _target, _buildInfo, _initializePlatform, _dartDefines);
      return true;
    }
    _client.startBuild();
    await for (BuildResults results in _client.buildResults) {
      final BuildResult result = results.results.firstWhere((BuildResult result) {
        return result.target == kBuildTargetName;
      });
      if (result.status == BuildStatus.failed) {
        return false;
      }
      if (result.status == BuildStatus.succeeded) {
        return true;
      }
    }
    return true;
  }

  /// Start the web compiler and asset server.
  static Future<WebFs> start({
    @required String target,
    @required FlutterProject flutterProject,
    @required BuildInfo buildInfo,
    @required bool skipDwds,
    @required bool initializePlatform,
    @required String hostname,
    @required String port,
    @required UrlTunneller urlTunneller,
    @required List<String> dartDefines,
  }) async {
    // workaround for https://github.com/flutter/flutter/issues/38290
    if (!flutterProject.dartTool.existsSync()) {
      flutterProject.dartTool.createSync(recursive: true);
    }
    // Workaround for https://github.com/flutter/flutter/issues/41681.
    final String toolPath = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools');
    if (!fs.isFileSync(fs.path.join(toolPath, '.packages'))) {
      await pub.get(
        context: PubContext.pubGet,
        directory: toolPath,
        offline: true,
        skipPubspecYamlCheck: true,
        checkLastModified: false,
      );
    }

    final Completer<bool> firstBuildCompleter = Completer<bool>();

    // Initialize the asset bundle.
    final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
    await assetBundle.build();
    await writeBundle(fs.directory(getAssetBuildDirectory()), assetBundle.entries);

    final String targetBaseName = fs.path
      .withoutExtension(target).replaceFirst('lib${fs.path.separator}', '');
    final Map<String, String> mappedUrls = <String, String>{
      'main.dart.js': 'packages/${flutterProject.manifest.appName}/'
          '${targetBaseName}_web_entrypoint.dart.js',
      '${targetBaseName}_web_entrypoint.dart.js.map': 'packages/${flutterProject.manifest.appName}/'
          '${targetBaseName}_web_entrypoint.dart.js.map',
      '${targetBaseName}_web_entrypoint.dart.bootstrap.js': 'packages/${flutterProject.manifest.appName}/'
          '${targetBaseName}_web_entrypoint.dart.bootstrap.js',
      '${targetBaseName}_web_entrypoint.digests': 'packages/${flutterProject.manifest.appName}/'
          '${targetBaseName}_web_entrypoint.digests',
    };

    // Initialize the dwds server.
    final String effectiveHostname = hostname ?? _kHostName;
    final int hostPort = port == null ? await os.findFreePort() : int.tryParse(port);

    final Pipeline pipeline = const Pipeline().addMiddleware((Handler innerHandler) {
      return (Request request) async {
        // Redirect the main.dart.js to the target file we decided to serve.
        if (mappedUrls.containsKey(request.url.path)) {
          final String newPath = mappedUrls[request.url.path];
          return innerHandler(
            Request(
              request.method,
              Uri.parse(request.requestedUri.toString()
                  .replaceFirst(request.requestedUri.path, '/$newPath')),
              headers: request.headers,
              url: Uri.parse(request.url.toString()
                  .replaceFirst(request.url.path, newPath)),
            ),
          );
        } else {
          return innerHandler(request);
        }
      };
    });

    Handler handler;
    Dwds dwds;
    BuildDaemonClient client;
    StreamSubscription<void> firstBuild;
    if (buildInfo.isDebug) {
      final bool hasWebPlugins = findPlugins(flutterProject)
          .any((Plugin p) => p.platforms.containsKey(WebPlugin.kConfigKey));
      // Start the build daemon and run an initial build.
      client = await buildDaemonCreator
        .startBuildDaemon(fs.currentDirectory.path,
            release: buildInfo.isRelease,
            profile: buildInfo.isProfile,
            hasPlugins: hasWebPlugins,
            initializePlatform: initializePlatform,
        );
      client.startBuild();
      // Only provide relevant build results
      final Stream<BuildResult> filteredBuildResults = client.buildResults
        .asyncMap<BuildResult>((BuildResults results) {
          return results.results
            .firstWhere((BuildResult result) => result.target == kBuildTargetName);
        });
      // Start the build daemon and run an initial build.
      firstBuild = client.buildResults.listen((BuildResults buildResults) {
        if (firstBuildCompleter.isCompleted) {
          return;
        }
        final BuildResult result = buildResults.results.firstWhere((BuildResult result) {
          return result.target == kBuildTargetName;
        });
        if (result.status == BuildStatus.failed) {
          firstBuildCompleter.complete(false);
        }
        if (result.status == BuildStatus.succeeded) {
          firstBuildCompleter.complete(true);
        }
      });
      final int daemonAssetPort = buildDaemonCreator.assetServerPort(fs.currentDirectory);

      // Initialize the asset bundle.
      final AssetBundle assetBundle = AssetBundleFactory.instance.createBundle();
      await assetBundle.build();
      await writeBundle(fs.directory(getAssetBuildDirectory()), assetBundle.entries);
      if (!skipDwds) {
        final BuildRunnerAssetHandler assetHandler = BuildRunnerAssetHandler(
          daemonAssetPort,
          kBuildTargetName,
          effectiveHostname,
          hostPort);
        dwds = await dwdsFactory(
          hostname: effectiveHostname,
          assetHandler: assetHandler,
          buildResults: filteredBuildResults,
          chromeConnection: () async {
            return (await ChromeLauncher.connectedInstance).chromeConnection;
          },
          reloadConfiguration: ReloadConfiguration.none,
          serveDevTools: false,
          verbose: false,
          enableDebugExtension: true,
          urlEncoder: urlTunneller,
          logWriter: (dynamic level, String message) => printTrace(message),
        );
        handler = pipeline.addHandler(dwds.handler);
      } else {
        handler = pipeline.addHandler(proxyHandler('http://localhost:$daemonAssetPort/web/'));
      }
    } else {
      await buildWeb(flutterProject, target, buildInfo, initializePlatform, dartDefines);
      firstBuildCompleter.complete(true);
    }

    final AssetServer assetServer = buildInfo.isDebug
      ? DebugAssetServer(flutterProject, targetBaseName)
      : ReleaseAssetServer();
    Cascade cascade = Cascade();
    cascade = cascade.add(handler);
    cascade = cascade.add(assetServer.handle);
    final HttpServer server = await httpMultiServerFactory(effectiveHostname, hostPort);
    shelf_io.serveRequests(server, cascade.handler);
    final WebFs webFS = WebFs(
      client,
      server,
      dwds,
      'http://$effectiveHostname:$hostPort/',
      assetServer,
      buildInfo.isDebug,
      flutterProject,
      target,
      buildInfo,
      initializePlatform,
      dartDefines,
    );
    if (!await firstBuildCompleter.future) {
      throw const BuildException();
    }
    await firstBuild?.cancel();
    return webFS;
  }
}

/// An exception thrown when build runner fails.
///
/// This contains no error information as it will have already been printed to
/// the console.
class BuildException implements Exception {
  const BuildException();
}

abstract class AssetServer {
  Future<Response> handle(Request request);

  void dispose() {}
}

class ReleaseAssetServer extends AssetServer {
  // Locations where source files, assets, or source maps may be located.
  final List<Uri> _searchPaths = <Uri>[
    fs.directory(getWebBuildDirectory()).uri,
    fs.directory(Cache.flutterRoot).parent.uri,
    fs.currentDirectory.childDirectory('lib').uri,
  ];

  @override
  Future<Response> handle(Request request) async {
    Uri fileUri;
    for (Uri uri in _searchPaths) {
      final Uri potential = uri.resolve(request.url.path);
      if (potential == null || !fs.isFileSync(potential.toFilePath())) {
        continue;
      }
      fileUri = potential;
      break;
    }

    if (fileUri != null) {
      final File file = fs.file(fileUri);
      final Uint8List bytes = file.readAsBytesSync();
      // Fallback to "application/octet-stream" on null which
      // makes no claims as to the structure of the data.
      final String mimeType = mime.lookupMimeType(file.path, headerBytes: bytes)
        ?? 'application/octet-stream';
      return Response.ok(bytes, headers: <String, String>{
        'Content-Type': mimeType,
      });
    }
    if (request.url.path == '') {
      final File file = fs.file(fs.path.join(getWebBuildDirectory(), 'index.html'));
      return Response.ok(file.readAsBytesSync(), headers: <String, String>{
        'Content-Type': 'text/html',
      });
    }
    return Response.notFound('');
  }
}

class DebugAssetServer extends AssetServer {
  DebugAssetServer(this.flutterProject, this.targetBaseName);

  final FlutterProject flutterProject;
  final String targetBaseName;
  final PackageMap packageMap = PackageMap(PackageMap.globalPackagesPath);
  Directory partFiles;

  @override
  Future<Response> handle(Request request) async {
    if (request.url.path.endsWith('.html')) {
      final Uri htmlUri = flutterProject.web.directory.uri.resolveUri(request.url);
      final File htmlFile = fs.file(htmlUri);
      if (htmlFile.existsSync()) {
        return Response.ok(htmlFile.readAsBytesSync(), headers: <String, String>{
          'Content-Type': 'text/html',
        });
      }
      return Response.notFound('');
    } else if (request.url.path.contains('stack_trace_mapper')) {
      final File file = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.engineDartSdkPath),
        'lib',
        'dev_compiler',
        'web',
        'dart_stack_trace_mapper.js',
      ));
      return Response.ok(file.readAsBytesSync(), headers: <String, String>{
        'Content-Type': 'text/javascript',
      });
    } else if (request.url.path.endsWith('part.js')) {
      // Lazily unpack any deferred imports in release/profile mode. These are
      // placed into an archive by build_runner, and are named based on the main
      // entrypoint + a "part" suffix (Though the actual names are arbitrary).
      // To make this easier to deal with they are copied into a temp directory.
      if (partFiles == null) {
        final File dart2jsArchive = fs.file(fs.path.join(
          flutterProject.dartTool.path,
          'build',
          'flutter_web',
          '${flutterProject.manifest.appName}',
          'lib',
          '${targetBaseName}_web_entrypoint.dart.js.tar.gz',
        ));
        if (dart2jsArchive.existsSync()) {
          final Archive archive = TarDecoder().decodeBytes(dart2jsArchive.readAsBytesSync());
          partFiles = fs.systemTempDirectory.createTempSync('flutter_tool.')
            ..createSync();
          for (ArchiveFile file in archive) {
            partFiles.childFile(file.name).writeAsBytesSync(file.content as List<int>);
          }
        }
      }
      final String fileName = fs.path.basename(request.url.path);
      return Response.ok(partFiles.childFile(fileName).readAsBytesSync(), headers: <String, String>{
        'Content-Type': 'text/javascript',
      });
    } else if (request.url.path.contains('require.js')) {
      final File file = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.engineDartSdkPath),
        'lib',
        'dev_compiler',
        'kernel',
        'amd',
        'require.js',
      ));
      return Response.ok(file.readAsBytesSync(), headers: <String, String>{
        'Content-Type': 'text/javascript',
      });
    } else if (request.url.path.endsWith('dart_sdk.js.map')) {
      final File file = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.flutterWebSdk),
        'kernel',
        'amd',
        'dart_sdk.js.map',
      ));
      return Response.ok(file.readAsBytesSync());
    } else if (request.url.path.endsWith('dart_sdk.js')) {
      final File file = fs.file(fs.path.join(
        artifacts.getArtifactPath(Artifact.flutterWebSdk),
        'kernel',
        'amd',
        'dart_sdk.js',
      ));
      return Response.ok(file.readAsBytesSync(), headers: <String, String>{
        'Content-Type': 'text/javascript',
      });
    } else if (request.url.path.endsWith('.dart')) {
      // This is likely a sourcemap request. The first segment is the
      // package name, and the rest is the path to the file relative to
      // the package uri. For example, `foo/bar.dart` would represent a
      // file at a path like `foo/lib/bar.dart`. If there is no leading
      // segment, then we assume it is from the current package.
      String basePath = request.url.path;
      basePath = basePath.replaceFirst('packages/build_web_compilers/', '');
      basePath = basePath.replaceFirst('packages/', '');

      // Handle sdk requests that have mangled urls from engine build.
      if (request.url.path.contains('dart-sdk')) {
        // Note: the request is a uri and not a file path, so they always use `/`.
        final String sdkPath = fs.path.joinAll(request.url.path.split('dart-sdk/').last.split('/'));
        final String dartSdkPath = artifacts.getArtifactPath(Artifact.engineDartSdkPath);
        final File candidateFile = fs.file(fs.path.join(dartSdkPath, sdkPath));
        return Response.ok(candidateFile.readAsBytesSync());
      }

      // See if it is a flutter sdk path.
      final String webSdkPath = artifacts.getArtifactPath(Artifact.flutterWebSdk);
      final File candidateFile = fs.file(fs.path.join(webSdkPath,
        basePath.split('/').join(platform.pathSeparator)));
      if (candidateFile.existsSync()) {
        return Response.ok(candidateFile.readAsBytesSync());
      }

      final String packageName = request.url.pathSegments.length == 1
          ? flutterProject.manifest.appName
          : request.url.pathSegments.first;
      String filePath = fs.path.joinAll(request.url.pathSegments.length == 1
          ? request.url.pathSegments
          : request.url.pathSegments.skip(1));
      String packagePath = packageMap.map[packageName]?.toFilePath(windows: platform.isWindows);
      // If the package isn't found, then we have an issue with relative
      // paths within the main project.
      if (packagePath == null) {
        packagePath = packageMap.map[flutterProject.manifest.appName]
            .toFilePath(windows: platform.isWindows);
        filePath = request.url.path;
      }
      final File file = fs.file(fs.path.join(packagePath, filePath));
      if (file.existsSync()) {
        return Response.ok(file.readAsBytesSync());
      }
      return Response.notFound('');
    } else if (request.url.path.contains('assets')) {
      final String assetPath = request.url.path.replaceFirst('assets/', '');
      final File file = fs.file(fs.path.join(getAssetBuildDirectory(), assetPath));
      if (file.existsSync()) {
        final Uint8List bytes = file.readAsBytesSync();
        // Fallback to "application/octet-stream" on null which
        // makes no claims as to the structure of the data.
        final String mimeType = mime.lookupMimeType(file.path, headerBytes: bytes)
          ?? 'application/octet-stream';
        return Response.ok(bytes, headers: <String, String>{
          'Content-Type': mimeType,
        });
      } else {
        return Response.notFound('');
      }
    }
    return Response.notFound('');
  }

  @override
  void dispose() {
    partFiles?.deleteSync(recursive: true);
  }
}

class ConnectionResult {
  ConnectionResult(this.appConnection, this.debugConnection);

  final AppConnection appConnection;
  final DebugConnection debugConnection;
}

class WebTestTargetManifest {
  WebTestTargetManifest(this.buildFilters);

  WebTestTargetManifest.all() : buildFilters = null;

  final List<String> buildFilters;

  bool get hasBuildFilters => buildFilters != null && buildFilters.isNotEmpty;
}

/// A testable interface for starting a build daemon.
class BuildDaemonCreator {
  const BuildDaemonCreator();

  // TODO(jonahwilliams): find a way to get build checks working for flutter for web.
  static const String _ignoredLine1 = 'Warning: Interpreting this as package URI';
  static const String _ignoredLine2 = 'build_script.dart was not found in the asset graph, incremental builds will not work';
  static const String _ignoredLine3 = 'have your dependencies specified fully in your pubspec.yaml';

  /// Start a build daemon and register the web targets.
  ///
  /// [initializePlatform] controls whether we should invoke [webOnlyInitializePlatform].
  Future<BuildDaemonClient> startBuildDaemon(String workingDirectory, {
    bool release = false,
    bool profile = false,
    bool hasPlugins = false,
    bool initializePlatform = true,
    WebTestTargetManifest testTargets,
  }) async {
    try {
      final BuildDaemonClient client = await _connectClient(
        workingDirectory,
        release: release,
        profile: profile,
        hasPlugins: hasPlugins,
        initializePlatform: initializePlatform,
        testTargets: testTargets,
      );
      _registerBuildTargets(client, testTargets);
      return client;
    } on OptionsSkew {
      throwToolExit(
        'Incompatible options with current running build daemon.\n\n'
        'Please stop other flutter_tool instances running in this directory '
        'before starting a new instance with these options.');
    }
    return null;
  }

  void _registerBuildTargets(
    BuildDaemonClient client,
    WebTestTargetManifest testTargets,
  ) {
    final OutputLocation outputLocation = OutputLocation((OutputLocationBuilder b) => b
      ..output = ''
      ..useSymlinks = true
      ..hoist = false);
    client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) => b
      ..target = 'web'
      ..outputLocation = outputLocation?.toBuilder()));
    if (testTargets != null) {
      client.registerBuildTarget(DefaultBuildTarget((DefaultBuildTargetBuilder b) {
        b.target = 'test';
        b.outputLocation = outputLocation?.toBuilder();
        if (testTargets.hasBuildFilters) {
          b.buildFilters.addAll(testTargets.buildFilters);
        }
        return b;
      }));
    }
  }

  Future<BuildDaemonClient> _connectClient(
    String workingDirectory, {
    bool release,
    bool profile,
    bool hasPlugins,
    bool initializePlatform,
    WebTestTargetManifest testTargets,
  }) {
    final String flutterToolsPackages = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools', '.packages');
    final String buildScript = fs.path.join(Cache.flutterRoot, 'packages', 'flutter_tools', 'lib', 'src', 'build_runner', 'build_script.dart');
    final String flutterWebSdk = artifacts.getArtifactPath(Artifact.flutterWebSdk);

    // On Windows we need to call the snapshot directly otherwise
    // the process will start in a disjoint cmd without access to
    // STDIO.
    final List<String> args = <String>[
      artifacts.getArtifactPath(Artifact.engineDartBinary),
      '--packages=$flutterToolsPackages',
      buildScript,
      'daemon',
      '--skip-build-script-check',
      '--define', 'flutter_tools:ddc=flutterWebSdk=$flutterWebSdk',
      '--define', 'flutter_tools:entrypoint=flutterWebSdk=$flutterWebSdk',
      '--define', 'flutter_tools:entrypoint=release=$release',
      '--define', 'flutter_tools:entrypoint=profile=$profile',
      '--define', 'flutter_tools:shell=flutterWebSdk=$flutterWebSdk',
      '--define', 'flutter_tools:shell=hasPlugins=$hasPlugins',
      '--define', 'flutter_tools:shell=initializePlatform=$initializePlatform',
      // The following will cause build runner to only build tests that were requested.
      if (testTargets != null && testTargets.hasBuildFilters)
        for (String buildFilter in testTargets.buildFilters)
          '--build-filter=$buildFilter',
    ];

    return BuildDaemonClient.connect(
      workingDirectory,
      args,
      logHandler: (ServerLog serverLog) {
        switch (serverLog.level) {
          case Level.SEVERE:
          case Level.SHOUT:
            // Ignore certain non-actionable messages on startup.
            if (serverLog.message.contains(_ignoredLine1) ||
                serverLog.message.contains(_ignoredLine2) ||
                serverLog.message.contains(_ignoredLine3)) {
              return;
            }
            printError(serverLog.message);
            if (serverLog.error != null) {
              printError(serverLog.error);
            }
            if (serverLog.stackTrace != null) {
              printTrace(serverLog.stackTrace);
            }
            break;
          default:
            if (serverLog.message.contains('Skipping compiling')) {
              printError(serverLog.message);
            } else {
              printTrace(serverLog.message);
            }
        }
      },
      buildMode: daemon.BuildMode.Manual,
    );
  }

  /// Retrieve the asset server port for the current daemon.
  int assetServerPort(Directory workingDirectory) {
    final String portFilePath = fs.path.join(daemon.daemonWorkspace(workingDirectory.path), '.asset_server_port');
    return int.tryParse(fs.file(portFilePath).readAsStringSync());
  }
}
