// 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:dwds/data/build_result.dart';
import 'package:dwds/dwds.dart';
import 'package:html/dom.dart';
import 'package:html/parser.dart';
import 'package:logging/logging.dart' as logging;
import 'package:meta/meta.dart';
import 'package:mime/mime.dart' as mime;
import 'package:package_config/package_config.dart';
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf;

import '../artifacts.dart';
import '../asset.dart';
import '../base/common.dart';
import '../base/file_system.dart';
import '../base/io.dart';
import '../base/logger.dart';
import '../base/net.dart';
import '../base/platform.dart';
import '../build_info.dart';
import '../bundle.dart';
import '../cache.dart';
import '../compile.dart';
import '../convert.dart';
import '../dart/package_map.dart';
import '../devfs.dart';
import '../globals.dart' as globals;
import '../project.dart';
import '../web/bootstrap.dart';
import '../web/chrome.dart';
import '../web/compile.dart';
import '../web/memory_fs.dart';

typedef DwdsLauncher = Future<Dwds> Function(
    {@required AssetReader assetReader,
    @required Stream<BuildResult> buildResults,
    @required ConnectionProvider chromeConnection,
    @required LoadStrategy loadStrategy,
    @required bool enableDebugging,
    ExpressionCompiler expressionCompiler,
    bool enableDebugExtension,
    String hostname,
    bool useSseForDebugProxy,
    bool useSseForDebugBackend,
    bool serveDevTools,
    UrlEncoder urlEncoder,
    bool spawnDds});

// A minimal index for projects that do not yet support web.
const String _kDefaultIndex = '''
<html>
    <head>
        <base href="/">
    </head>
    <body>
        <script src="main.dart.js"></script>
    </body>
</html>
''';

/// An expression compiler connecting to FrontendServer.
///
/// This is only used in development mode.
class WebExpressionCompiler implements ExpressionCompiler {
  WebExpressionCompiler(this._generator);

  final ResidentCompiler _generator;

  @override
  Future<ExpressionCompilationResult> compileExpressionToJs(
    String isolateId,
    String libraryUri,
    int line,
    int column,
    Map<String, String> jsModules,
    Map<String, String> jsFrameValues,
    String moduleName,
    String expression,
  ) async {
    final CompilerOutput compilerOutput =
        await _generator.compileExpressionToJs(libraryUri, line, column,
            jsModules, jsFrameValues, moduleName, expression);

    if (compilerOutput != null && compilerOutput.outputFilename != null) {
      final String content = utf8.decode(
          globals.fs.file(compilerOutput.outputFilename).readAsBytesSync());
      return ExpressionCompilationResult(
          content, compilerOutput.errorCount > 0);
    }

    return ExpressionCompilationResult(
        'InternalError: frontend server failed to compile \'$expression\'',
        true);
  }

  @override
  Future<bool> updateDependencies(Map<String, String> modules) async => true;
}

/// A web server which handles serving JavaScript and assets.
///
/// This is only used in development mode.
class WebAssetServer implements AssetReader {
  @visibleForTesting
  WebAssetServer(
    this._httpServer,
    this._packages,
    this.internetAddress,
    this._modules,
    this._digests,
    this._nullSafetyMode,
  ) : basePath = _parseBasePathFromIndexHtml(globals.fs.currentDirectory
            .childDirectory('web')
            .childFile('index.html'));

  // Fallback to "application/octet-stream" on null which
  // makes no claims as to the structure of the data.
  static const String _kDefaultMimeType = 'application/octet-stream';

  final Map<String, String> _modules;
  final Map<String, String> _digests;

  int get selectedPort => _httpServer.port;

  void performRestart(List<String> modules) {
    for (final String module in modules) {
      // We skip computing the digest by using the hashCode of the underlying buffer.
      // Whenever a file is updated, the corresponding Uint8List.view it corresponds
      // to will change.
      final String moduleName =
          module.startsWith('/') ? module.substring(1) : module;
      final String name = moduleName.replaceAll('.lib.js', '');
      final String path = moduleName.replaceAll('.js', '');
      _modules[name] = path;
      _digests[name] = _webMemoryFS.files[moduleName].hashCode.toString();
    }
  }

  @visibleForTesting
  List<String> write(
    File codeFile,
    File manifestFile,
    File sourcemapFile,
    File metadataFile,
  ) {
    return _webMemoryFS.write(codeFile, manifestFile, sourcemapFile, metadataFile);
  }

  /// Start the web asset server on a [hostname] and [port].
  ///
  /// If [testMode] is true, do not actually initialize dwds or the shelf static
  /// server.
  ///
  /// Unhandled exceptions will throw a [ToolExit] with the error and stack
  /// trace.
  static Future<WebAssetServer> start(
    ChromiumLauncher chromiumLauncher,
    String hostname,
    int port,
    UrlTunneller urlTunneller,
    bool useSseForDebugProxy,
    bool useSseForDebugBackend,
    BuildInfo buildInfo,
    bool enableDwds,
    Uri entrypoint,
    ExpressionCompiler expressionCompiler,
    NullSafetyMode nullSafetyMode, {
    bool testMode = false,
    DwdsLauncher dwdsLauncher = Dwds.start,
  }) async {
    InternetAddress address;
    if (hostname == 'any') {
      address = InternetAddress.anyIPv4;
    } else {
      address = (await InternetAddress.lookup(hostname)).first;
    }
    HttpServer httpServer;
    dynamic lastError;
    for (int i = 0; i < 5; i += 1) {
      try {
        httpServer = await HttpServer.bind(address, port ?? await globals.os.findFreePort());
        break;
      } on SocketException catch (error) {
        lastError = error;
        await Future<void>.delayed(const Duration(milliseconds: 100));
      }
    }
    if (httpServer == null) {
      throwToolExit('Failed to bind web development server:\n$lastError');
    }

    // Allow rendering in a iframe.
    httpServer.defaultResponseHeaders.remove('x-frame-options', 'SAMEORIGIN');

    final PackageConfig packageConfig = buildInfo.packageConfig;
    final Map<String, String> digests = <String, String>{};
    final Map<String, String> modules = <String, String>{};
    final WebAssetServer server = WebAssetServer(
      httpServer,
      packageConfig,
      address,
      modules,
      digests,
      nullSafetyMode,
    );
    if (testMode) {
      return server;
    }

    // In release builds deploy a simpler proxy server.
    if (buildInfo.mode != BuildMode.debug) {
      final ReleaseAssetServer releaseAssetServer = ReleaseAssetServer(
        entrypoint,
        fileSystem: globals.fs,
        platform: globals.platform,
        flutterRoot: Cache.flutterRoot,
        webBuildDirectory: getWebBuildDirectory(),
        basePath: server.basePath,
      );
      shelf.serveRequests(httpServer, releaseAssetServer.handle);
      return server;
    }

    // Return a version string for all active modules. This is populated
    // along with the `moduleProvider` update logic.
    Future<Map<String, String>> _digestProvider() async => digests;

    // Ensure dwds is present and provide middleware to avoid trying to
    // load the through the isolate APIs.
    final Directory directory =
        await _loadDwdsDirectory(globals.fs, globals.logger);
    final shelf.Middleware middleware =
        (FutureOr<shelf.Response> Function(shelf.Request) innerHandler) {
      return (shelf.Request request) async {
        if (request.url.path.endsWith('dwds/src/injected/client.js')) {
          final Uri uri = directory.uri.resolve('src/injected/client.js');
          final String result =
              await globals.fs.file(uri.toFilePath()).readAsString();
          return shelf.Response.ok(result, headers: <String, String>{
            HttpHeaders.contentTypeHeader: 'application/javascript'
          });
        }
        return innerHandler(request);
      };
    };

    logging.Logger.root.onRecord.listen((logging.LogRecord event) {
      globals.printTrace('${event.loggerName}: ${event.message}');
    });

    // In debug builds, spin up DWDS and the full asset server.
    final Dwds dwds = await dwdsLauncher(
      assetReader: server,
      enableDebugExtension: true,
      buildResults: const Stream<BuildResult>.empty(),
      chromeConnection: () async {
        final Chromium chromium = await chromiumLauncher.connectedInstance;
        return chromium.chromeConnection;
      },
      hostname: hostname,
      urlEncoder: urlTunneller,
      enableDebugging: true,
      useSseForDebugProxy: useSseForDebugProxy,
      useSseForDebugBackend: useSseForDebugBackend,
      serveDevTools: false,
      loadStrategy: FrontendServerRequireStrategyProvider(
        ReloadConfiguration.none,
        server,
        _digestProvider,
      ).strategy,
      expressionCompiler: expressionCompiler,
      spawnDds: true,
    );
    shelf.Pipeline pipeline = const shelf.Pipeline();
    if (enableDwds) {
      pipeline = pipeline.addMiddleware(middleware);
      pipeline = pipeline.addMiddleware(dwds.middleware);
    }
    final shelf.Handler dwdsHandler =
        pipeline.addHandler(server.handleRequest);
    final shelf.Cascade cascade =
        shelf.Cascade().add(dwds.handler).add(dwdsHandler);
    shelf.serveRequests(httpServer, cascade.handler);
    server.dwds = dwds;
    return server;
  }

  final NullSafetyMode _nullSafetyMode;
  final HttpServer _httpServer;
  final WebMemoryFS _webMemoryFS = WebMemoryFS();


  final PackageConfig _packages;
  final InternetAddress internetAddress;
  /* late final */ Dwds dwds;
  Directory entrypointCacheDirectory;

  @visibleForTesting
  HttpHeaders get defaultResponseHeaders => _httpServer.defaultResponseHeaders;

  @visibleForTesting
  Uint8List getFile(String path) => _webMemoryFS.files[path];

  @visibleForTesting
  Uint8List getSourceMap(String path) => _webMemoryFS.sourcemaps[path];

  @visibleForTesting
  Uint8List getMetadata(String path) => _webMemoryFS.metadataFiles[path];

  @visibleForTesting

  /// The base path to serve from.
  ///
  /// It should have no leading or trailing slashes.
  String basePath = '';

  // handle requests for JavaScript source, dart sources maps, or asset files.
  @visibleForTesting
  Future<shelf.Response> handleRequest(shelf.Request request) async {
    if (request.method != 'GET') {
      // Assets are served via GET only.
      return shelf.Response.notFound('');
    }

    final String requestPath = _stripBasePath(request.url.path, basePath);

    if (requestPath == null) {
      return shelf.Response.notFound('');
    }

    // If the response is `/`, then we are requesting the index file.
    if (requestPath == '/' || requestPath.isEmpty) {
      return _serveIndex();
    }

    final Map<String, String> headers = <String, String>{};

    // Track etag headers for better caching of resources.
    final String ifNoneMatch = request.headers[HttpHeaders.ifNoneMatchHeader];
    headers[HttpHeaders.cacheControlHeader] = 'max-age=0, must-revalidate';

    // If this is a JavaScript file, it must be in the in-memory cache.
    // Attempt to look up the file by URI.
    final String webServerPath =
        requestPath.replaceFirst('.dart.js', '.dart.lib.js');
    if (_webMemoryFS.files.containsKey(requestPath) || _webMemoryFS.files.containsKey(webServerPath)) {
      final List<int> bytes = getFile(requestPath) ?? getFile(webServerPath);
      // Use the underlying buffer hashCode as a revision string. This buffer is
      // replaced whenever the frontend_server produces new output files, which
      // will also change the hashCode.
      final String etag = bytes.hashCode.toString();
      if (ifNoneMatch == etag) {
        return shelf.Response.notModified();
      }
      headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
      headers[HttpHeaders.contentTypeHeader] = 'application/javascript';
      headers[HttpHeaders.etagHeader] = etag;
      return shelf.Response.ok(bytes, headers: headers);
    }
    // If this is a sourcemap file, then it might be in the in-memory cache.
    // Attempt to lookup the file by URI.
    if (_webMemoryFS.sourcemaps.containsKey(requestPath)) {
      final List<int> bytes = getSourceMap(requestPath);
      final String etag = bytes.hashCode.toString();
      if (ifNoneMatch == etag) {
        return shelf.Response.notModified();
      }
      headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
      headers[HttpHeaders.contentTypeHeader] = 'application/json';
      headers[HttpHeaders.etagHeader] = etag;
      return shelf.Response.ok(bytes, headers: headers);
    }

    // If this is a metadata file, then it might be in the in-memory cache.
    // Attempt to lookup the file by URI.
    if (_webMemoryFS.metadataFiles.containsKey(requestPath)) {
      final List<int> bytes = getMetadata(requestPath);
      final String etag = bytes.hashCode.toString();
      if (ifNoneMatch == etag) {
        return shelf.Response.notModified();
      }
      headers[HttpHeaders.contentLengthHeader] = bytes.length.toString();
      headers[HttpHeaders.contentTypeHeader] = 'application/json';
      headers[HttpHeaders.etagHeader] = etag;
      return shelf.Response.ok(bytes, headers: headers);
    }

    File file = _resolveDartFile(requestPath);

    // If all of the lookups above failed, the file might have been an asset.
    // Try and resolve the path relative to the built asset directory.
    if (!file.existsSync()) {
      final Uri potential = globals.fs
          .directory(getAssetBuildDirectory())
          .uri
          .resolve(requestPath.replaceFirst('assets/', ''));
      file = globals.fs.file(potential);
    }

    if (!file.existsSync()) {
      final Uri webPath = globals.fs.currentDirectory
          .childDirectory('web')
          .uri
          .resolve(requestPath);
      file = globals.fs.file(webPath);
    }

    if (!file.existsSync()) {
      // Paths starting with these prefixes should've been resolved above.
      if (requestPath.startsWith('assets/') ||
          requestPath.startsWith('packages/')) {
        return shelf.Response.notFound('');
      }
      return _serveIndex();
    }

    // For real files, use a serialized file stat plus path as a revision.
    // This allows us to update between canvaskit and non-canvaskit SDKs.
    final String etag = file.lastModifiedSync().toIso8601String() +
        Uri.encodeComponent(file.path);
    if (ifNoneMatch == etag) {
      return shelf.Response.notModified();
    }

    final int length = file.lengthSync();
    // Attempt to determine the file's mime type. if this is not provided some
    // browsers will refuse to render images/show video etc. If the tool
    // cannot determine a mime type, fall back to application/octet-stream.
    String mimeType;
    if (length >= 12) {
      mimeType = mime.lookupMimeType(
        file.path,
        headerBytes: await file.openRead(0, 12).first,
      );
    }
    mimeType ??= _kDefaultMimeType;
    headers[HttpHeaders.contentLengthHeader] = length.toString();
    headers[HttpHeaders.contentTypeHeader] = mimeType;
    headers[HttpHeaders.etagHeader] = etag;
    return shelf.Response.ok(file.openRead(), headers: headers);
  }

  /// Tear down the http server running.
  Future<void> dispose() {
    return _httpServer.close();
  }

  /// Write a single file into the in-memory cache.
  void writeFile(String filePath, String contents) {
    writeBytes(filePath, utf8.encode(contents) as Uint8List);
  }

  void writeBytes(String filePath, Uint8List contents) {
    _webMemoryFS.files[filePath] = contents;
  }

  /// Determines what rendering backed to use.
  WebRendererMode webRenderer = WebRendererMode.html;

  shelf.Response _serveIndex() {
    final Map<String, String> headers = <String, String>{
      HttpHeaders.contentTypeHeader: 'text/html',
    };
    final File indexFile = globals.fs.currentDirectory
        .childDirectory('web')
        .childFile('index.html');

    if (indexFile.existsSync()) {
      headers[HttpHeaders.contentLengthHeader] =
          indexFile.lengthSync().toString();
      return shelf.Response.ok(indexFile.openRead(), headers: headers);
    }

    headers[HttpHeaders.contentLengthHeader] = _kDefaultIndex.length.toString();
    return shelf.Response.ok(_kDefaultIndex, headers: headers);
  }

  // Attempt to resolve `path` to a dart file.
  File _resolveDartFile(String path) {
    // Return the actual file objects so that local engine changes are automatically picked up.
    switch (path) {
      case 'dart_sdk.js':
        return _resolveDartSdkJsFile;
      case 'dart_sdk.js.map':
        return _resolveDartSdkJsMapFile;
    }
    // This is the special generated entrypoint.
    if (path == 'web_entrypoint.dart') {
      return entrypointCacheDirectory.childFile('web_entrypoint.dart');
    }

    // If this is a dart file, it must be on the local file system and is
    // likely coming from a source map request. The tool doesn't currently
    // consider the case of Dart files as assets.
    final File dartFile =
        globals.fs.file(globals.fs.currentDirectory.uri.resolve(path));
    if (dartFile.existsSync()) {
      return dartFile;
    }

    final List<String> segments = path.split('/');
    if (segments.first.isEmpty) {
      segments.removeAt(0);
    }

    // The file might have been a package file which is signaled by a
    // `/packages/<package>/<path>` request.
    if (segments.first == 'packages') {
      final Uri filePath = _packages
          .resolve(Uri(scheme: 'package', pathSegments: segments.skip(1)));
      if (filePath != null) {
        final File packageFile = globals.fs.file(filePath);
        if (packageFile.existsSync()) {
          return packageFile;
        }
      }
    }

    // Otherwise it must be a Dart SDK source or a Flutter Web SDK source.
    final Directory dartSdkParent = globals.fs
        .directory(
            globals.artifacts.getArtifactPath(Artifact.engineDartSdkPath))
        .parent;
    final File dartSdkFile = globals.fs.file(dartSdkParent.uri.resolve(path));
    if (dartSdkFile.existsSync()) {
      return dartSdkFile;
    }

    final Directory flutterWebSdk = globals.fs
        .directory(globals.artifacts.getArtifactPath(Artifact.flutterWebSdk));
    final File webSdkFile = globals.fs.file(flutterWebSdk.uri.resolve(path));

    return webSdkFile;
  }

  File get _resolveDartSdkJsFile =>
      globals.fs.file(globals.artifacts.getArtifactPath(
          kDartSdkJsArtifactMap[webRenderer][_nullSafetyMode]
      ));

  File get _resolveDartSdkJsMapFile =>
    globals.fs.file(globals.artifacts.getArtifactPath(
        kDartSdkJsMapArtifactMap[webRenderer][_nullSafetyMode]
    ));

  @override
  Future<String> dartSourceContents(String serverPath) async {
    final File result = _resolveDartFile(serverPath);
    if (result.existsSync()) {
      return result.readAsString();
    }
    return null;
  }

  @override
  Future<String> sourceMapContents(String serverPath) async {
    return utf8.decode(_webMemoryFS.sourcemaps[serverPath]);
  }

  @override
  Future<String> metadataContents(String serverPath) async {
    if (serverPath == 'main_module.ddc_merged_metadata') {
      return _webMemoryFS.mergedMetadata;
    }
    if (_webMemoryFS.metadataFiles.containsKey(serverPath)) {
      return utf8.decode(_webMemoryFS.metadataFiles[serverPath]);
    }
    return null;
  }

  @override
  Future<void> close() async {}
}

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

  final AppConnection appConnection;
  final DebugConnection debugConnection;
}

/// The web specific DevFS implementation.
class WebDevFS implements DevFS {
  /// Create a new [WebDevFS] instance.
  ///
  /// [testMode] is true, do not actually initialize dwds or the shelf static
  /// server.
  WebDevFS({
    @required this.hostname,
    @required int port,
    @required this.packagesFilePath,
    @required this.urlTunneller,
    @required this.useSseForDebugProxy,
    @required this.useSseForDebugBackend,
    @required this.buildInfo,
    @required this.enableDwds,
    @required this.entrypoint,
    @required this.expressionCompiler,
    @required this.chromiumLauncher,
    @required this.nullAssertions,
    @required this.nativeNullAssertions,
    @required this.nullSafetyMode,
    this.testMode = false,
  }) : _port = port;

  final Uri entrypoint;
  final String hostname;
  final String packagesFilePath;
  final UrlTunneller urlTunneller;
  final bool useSseForDebugProxy;
  final bool useSseForDebugBackend;
  final BuildInfo buildInfo;
  final bool enableDwds;
  final bool testMode;
  final ExpressionCompiler expressionCompiler;
  final ChromiumLauncher chromiumLauncher;
  final bool nullAssertions;
  final bool nativeNullAssertions;
  final int _port;
  final NullSafetyMode nullSafetyMode;

  WebAssetServer webAssetServer;

  Dwds get dwds => webAssetServer.dwds;

  Future<DebugConnection> _cachedExtensionFuture;
  StreamSubscription<void> _connectedApps;

  /// 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 {
      try {
        final DebugConnection debugConnection = useDebugExtension
            ? await (_cachedExtensionFuture ??=
                dwds.extensionDebugConnections.stream.first)
            : await dwds.debugConnection(appConnection);
        if (firstConnection.isCompleted) {
          appConnection.runMain();
        } else {
          firstConnection
              .complete(ConnectionResult(appConnection, debugConnection));
        }
      } on Exception catch (error, stackTrace) {
        if (!firstConnection.isCompleted) {
          firstConnection.completeError(error, stackTrace);
        }
      }
    }, onError: (dynamic error, StackTrace stackTrace) {
      globals.printError(
          'Unknown error while waiting for debug connection:$error\n$stackTrace');
      if (!firstConnection.isCompleted) {
        firstConnection.completeError(error, stackTrace);
      }
    });
    return firstConnection.future;
  }

  @override
  List<Uri> sources = <Uri>[];

  @override
  DateTime lastCompiled;

  @override
  PackageConfig lastPackageConfig;

  // We do not evict assets on the web.
  @override
  Set<String> get assetPathsToEvict => const <String>{};

  @override
  Uri get baseUri => _baseUri;
  Uri _baseUri;

  @override
  Future<Uri> create() async {
    webAssetServer = await WebAssetServer.start(
      chromiumLauncher,
      hostname,
      _port,
      urlTunneller,
      useSseForDebugProxy,
      useSseForDebugBackend,
      buildInfo,
      enableDwds,
      entrypoint,
      expressionCompiler,
      nullSafetyMode,
      testMode: testMode,
    );
    final int selectedPort = webAssetServer.selectedPort;
    if (buildInfo.dartDefines.contains('FLUTTER_WEB_AUTO_DETECT=true')) {
      webAssetServer.webRenderer = WebRendererMode.autoDetect;
    } else if (buildInfo.dartDefines.contains('FLUTTER_WEB_USE_SKIA=true')) {
      webAssetServer.webRenderer = WebRendererMode.canvaskit;
    }
    if (hostname == 'any') {
      _baseUri = Uri.http('localhost:$selectedPort', '');
    } else {
      _baseUri = Uri.http('$hostname:$selectedPort', '');
    }
    return _baseUri;
  }

  @override
  Future<void> destroy() async {
    await webAssetServer.dispose();
    await _connectedApps?.cancel();
  }

  @override
  Uri deviceUriToHostUri(Uri deviceUri) {
    return deviceUri;
  }

  @override
  String get fsName => 'web_asset';

  @override
  Directory get rootDirectory => null;

  @override
  Future<UpdateFSReport> update({
    @required Uri mainUri,
    @required ResidentCompiler generator,
    @required bool trackWidgetCreation,
    @required String pathToReload,
    @required List<Uri> invalidatedFiles,
    @required PackageConfig packageConfig,
    @required String dillOutputPath,
    DevFSWriter devFSWriter,
    String target,
    AssetBundle bundle,
    DateTime firstBuildTime,
    bool bundleFirstUpload = false,
    bool fullRestart = false,
    String projectRootPath,
  }) async {
    assert(trackWidgetCreation != null);
    assert(generator != null);
    lastPackageConfig = packageConfig;
    final File mainFile = globals.fs.file(mainUri);
    final String outputDirectoryPath = mainFile.parent.path;

    if (bundleFirstUpload) {
      webAssetServer.entrypointCacheDirectory =
          globals.fs.directory(outputDirectoryPath);
      generator.addFileSystemRoot(outputDirectoryPath);
      final String entrypoint = globals.fs.path.basename(mainFile.path);
      webAssetServer.writeBytes(entrypoint, mainFile.readAsBytesSync());
      webAssetServer.writeBytes('require.js', requireJS.readAsBytesSync());
      webAssetServer.writeBytes(
          'stack_trace_mapper.js', stackTraceMapper.readAsBytesSync());
      webAssetServer.writeFile(
          'manifest.json', '{"info":"manifest not generated in run mode."}');
      webAssetServer.writeFile('flutter_service_worker.js',
          '// Service worker not loaded in run mode.');
      webAssetServer.writeFile(
          'version.json', FlutterProject.current().getVersionInfo());
      webAssetServer.writeFile(
        'main.dart.js',
        generateBootstrapScript(
          requireUrl: 'require.js',
          mapperUrl: 'stack_trace_mapper.js',
        ),
      );
      webAssetServer.writeFile(
        'main_module.bootstrap.js',
        generateMainModule(
          entrypoint: entrypoint,
          nullAssertions: nullAssertions,
          nativeNullAssertions: nativeNullAssertions,
        ),
      );
      // TODO(jonahwilliams): refactor the asset code in this and the regular devfs to
      // be shared.
      if (bundle != null) {
        await writeBundle(
          globals.fs.directory(getAssetBuildDirectory()),
          bundle.entries,
        );
      }
    }
    final DateTime candidateCompileTime = DateTime.now();
    if (fullRestart) {
      generator.reset();
    }

    // The tool generates an entrypoint file in a temp directory to handle
    // the web specific bootstrap logic. To make it easier for DWDS to handle
    // mapping the file name, this is done via an additional file root and
    // special hard-coded scheme.
    final CompilerOutput compilerOutput = await generator.recompile(
      Uri(
        scheme: 'org-dartlang-app',
        path: '/' + mainUri.pathSegments.last,
      ),
      invalidatedFiles,
      outputPath: dillOutputPath,
      packageConfig: packageConfig,
    );
    if (compilerOutput == null || compilerOutput.errorCount > 0) {
      return UpdateFSReport(success: false);
    }

    // Only update the last compiled time if we successfully compiled.
    lastCompiled = candidateCompileTime;
    // list of sources that needs to be monitored are in [compilerOutput.sources]
    sources = compilerOutput.sources;
    File codeFile;
    File manifestFile;
    File sourcemapFile;
    File metadataFile;
    List<String> modules;
    try {
      final Directory parentDirectory = globals.fs.directory(outputDirectoryPath);
      codeFile = parentDirectory.childFile('${compilerOutput.outputFilename}.sources');
      manifestFile = parentDirectory.childFile('${compilerOutput.outputFilename}.json');
      sourcemapFile = parentDirectory.childFile('${compilerOutput.outputFilename}.map');
      metadataFile = parentDirectory.childFile('${compilerOutput.outputFilename}.metadata');
      modules = webAssetServer._webMemoryFS.write(codeFile, manifestFile, sourcemapFile, metadataFile);
    } on FileSystemException catch (err) {
      throwToolExit('Failed to load recompiled sources:\n$err');
    }
    webAssetServer.performRestart(modules);
    return UpdateFSReport(
      success: true,
      syncedBytes: codeFile.lengthSync(),
      invalidatedSourcesCount: invalidatedFiles.length,
    );
  }

  @visibleForTesting
  final File requireJS = globals.fs.file(globals.fs.path.join(
    globals.artifacts.getArtifactPath(Artifact.engineDartSdkPath),
    'lib',
    'dev_compiler',
    'kernel',
    'amd',
    'require.js',
  ));

  @visibleForTesting
  final File stackTraceMapper = globals.fs.file(globals.fs.path.join(
    globals.artifacts.getArtifactPath(Artifact.engineDartSdkPath),
    'lib',
    'dev_compiler',
    'web',
    'dart_stack_trace_mapper.js',
  ));

  @override
  void resetLastCompiled() {
    // Not used for web compilation.
  }
}

class ReleaseAssetServer {
  ReleaseAssetServer(
    this.entrypoint, {
    @required FileSystem fileSystem,
    @required String webBuildDirectory,
    @required String flutterRoot,
    @required Platform platform,
    this.basePath = '',
  })  : _fileSystem = fileSystem,
        _platform = platform,
        _flutterRoot = flutterRoot,
        _webBuildDirectory = webBuildDirectory,
        _fileSystemUtils =
            FileSystemUtils(fileSystem: fileSystem, platform: platform);

  final Uri entrypoint;
  final String _flutterRoot;
  final String _webBuildDirectory;
  final FileSystem _fileSystem;
  final FileSystemUtils _fileSystemUtils;
  final Platform _platform;

  @visibleForTesting

  /// The base path to serve from.
  ///
  /// It should have no leading or trailing slashes.
  final String basePath;

  // Locations where source files, assets, or source maps may be located.
  List<Uri> _searchPaths() => <Uri>[
        _fileSystem.directory(_webBuildDirectory).uri,
        _fileSystem.directory(_flutterRoot).uri,
        _fileSystem.directory(_flutterRoot).parent.uri,
        _fileSystem.currentDirectory.uri,
        _fileSystem.directory(_fileSystemUtils.homeDirPath).uri,
      ];

  Future<shelf.Response> handle(shelf.Request request) async {
    if (request.method != 'GET') {
      // Assets are served via GET only.
      return shelf.Response.notFound('');
    }

    Uri fileUri;
    final String requestPath = _stripBasePath(request.url.path, basePath);

    if (requestPath == null) {
      return shelf.Response.notFound('');
    }

    if (request.url.toString() == 'main.dart') {
      fileUri = entrypoint;
    } else {
      for (final Uri uri in _searchPaths()) {
        final Uri potential = uri.resolve(requestPath);
        if (potential == null ||
            !_fileSystem.isFileSync(
                potential.toFilePath(windows: _platform.isWindows))) {
          continue;
        }
        fileUri = potential;
        break;
      }
    }
    if (fileUri != null) {
      final File file = _fileSystem.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 shelf.Response.ok(bytes, headers: <String, String>{
        'Content-Type': mimeType,
      });
    }

    final File file = _fileSystem
        .file(_fileSystem.path.join(_webBuildDirectory, 'index.html'));
    return shelf.Response.ok(file.readAsBytesSync(), headers: <String, String>{
      'Content-Type': 'text/html',
    });
  }
}

Future<Directory> _loadDwdsDirectory(
    FileSystem fileSystem, Logger logger) async {
  final String toolPackagePath =
      fileSystem.path.join(Cache.flutterRoot, 'packages', 'flutter_tools');
  final String packageFilePath =
      fileSystem.path.join(toolPackagePath, '.dart_tool', 'package_config.json');
  final PackageConfig packageConfig = await loadPackageConfigWithLogging(
    fileSystem.file(packageFilePath),
    logger: logger,
  );
  return fileSystem.directory(packageConfig['dwds'].packageUriRoot);
}

String _stripBasePath(String path, String basePath) {
  path = _stripLeadingSlashes(path);
  if (path.startsWith(basePath)) {
    path = path.substring(basePath.length);
  } else {
    // The given path isn't under base path, return null to indicate that.
    return null;
  }
  return _stripLeadingSlashes(path);
}

String _stripLeadingSlashes(String path) {
  while (path.startsWith('/')) {
    path = path.substring(1);
  }
  return path;
}

String _stripTrailingSlashes(String path) {
  while (path.endsWith('/')) {
    path = path.substring(0, path.length - 1);
  }
  return path;
}

String _parseBasePathFromIndexHtml(File indexHtml) {
  final String htmlContent =
      indexHtml.existsSync() ? indexHtml.readAsStringSync() : _kDefaultIndex;

  final Document document = parse(htmlContent);
  final Element baseElement = document.querySelector('base');
  String baseHref =
      baseElement?.attributes == null ? null : baseElement.attributes['href'];

  if (baseHref == null) {
    baseHref = '';
  } else if (!baseHref.startsWith('/')) {
    throw ToolExit(
      'Error: The base href in "web/index.html" must be absolute (i.e. start '
      'with a "/"), but found: `${baseElement.outerHtml}`.\n'
      '$basePathExample',
    );
  } else if (!baseHref.endsWith('/')) {
    throw ToolExit(
      'Error: The base href in "web/index.html" must end with a "/", but found: `${baseElement.outerHtml}`.\n'
      '$basePathExample',
    );
  } else {
    baseHref = _stripLeadingSlashes(_stripTrailingSlashes(baseHref));
  }

  return baseHref;
}

const String basePathExample = '''
For example, to serve from the root use:

    <base href="/">

To serve from a subpath "foo" (i.e. http://localhost:8080/foo/ instead of http://localhost:8080/) use:

    <base href="/foo/">

For more information, see: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/base
''';
