// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:convert' show HtmlEscape;
import 'dart:io' hide BytesBuilder;
import 'dart:typed_data' show BytesBuilder;

import 'package:package_config/package_config.dart';
import 'package:test_runner/src/configuration.dart';
import 'package:test_runner/src/repository.dart';
import 'package:test_runner/src/utils.dart';

class DispatchingServer {
  final HttpServer server;
  final Map<String, Function> _handlers = {};
  final void Function(HttpRequest request) _notFound;

  DispatchingServer(this.server, Function? onError, this._notFound) {
    server.listen(_dispatchRequest, onError: onError);
  }

  void addHandler(String prefix, void Function(HttpRequest request) handler) {
    _handlers[prefix] = handler;
  }

  void _dispatchRequest(HttpRequest request) {
    // If the request path matches a prefix in _handlers, send it to that
    // handler.  Otherwise, run the notFound handler.
    for (var prefix in _handlers.keys) {
      if (request.uri.path.startsWith(prefix)) {
        _handlers[prefix]!(request);
        return;
      }
    }
    _notFound(request);
  }
}

/// Interface of the HTTP server:
///
/// /echo: This will stream the data received in the request stream back
///        to the client.
/// /root_dart/X: This will serve the corresponding file from the dart
///               directory (i.e. '$DartDirectory/X').
/// /root_build/X: This will serve the corresponding file from the build
///                directory (i.e. '$BuildDirectory/X').
/// /FOO/packages/PAZ/BAR: This will serve files from the packages listed in
///      the package spec .packages.  Supports a package
///      root or custom package spec, and uses $dart_dir/.packages
///      as the default. This will serve file lib/BAR from the package PAZ.
/// /ws: This will upgrade the connection to a WebSocket connection and echo
///      all data back to the client.
///
/// In case a path does not refer to a file but rather to a directory, a
/// directory listing will be displayed.

const prefixBuildDir = 'root_build';
const prefixDartDir = 'root_dart';

/// Runs a set of servers that are initialized specifically for the needs of our
/// test framework, such as dealing with package-root.
class TestingServers {
  static final _cacheExpirationSeconds = 30;
  static final _harmlessRequestPathSuffixes = [
    "/apple-touch-icon.png",
    "/apple-touch-icon-precomposed.png",
    "/favicon.ico",
    "/foo",
    "/bar",
    "/NonExistingFile",
    "IntentionallyMissingFile",
  ];

  final List<HttpServer> _serverList = [];
  final Uri _buildDirectory;
  final Uri _dartDirectory;
  final Uri _packages;
  late PackageConfig _packageConfig;
  final bool useContentSecurityPolicy;
  final Runtime runtime;
  DispatchingServer? _server;

  TestingServers._(
    this.useContentSecurityPolicy,
    this._buildDirectory,
    this._dartDirectory,
    this._packages,
    this.runtime,
  );

  factory TestingServers(
    String buildDirectory,
    bool useContentSecurityPolicy, [
    Runtime runtime = Runtime.none,
    String? dartDirectory,
    String? packages,
  ]) {
    var buildDirectoryUri = Uri.base.resolveUri(Uri.directory(buildDirectory));
    var dartDirectoryUri = dartDirectory == null
        ? Repository.uri
        : Uri.base.resolveUri(Uri.directory(dartDirectory));
    var packagesUri = packages == null
        ? dartDirectoryUri.resolve('.dart_tool/package_config.json')
        : Uri.file(packages);
    return TestingServers._(
      useContentSecurityPolicy,
      buildDirectoryUri,
      dartDirectoryUri,
      packagesUri,
      runtime,
    );
  }

  String get network => _serverList[0].address.address;

  int get port => _serverList[0].port;

  int get crossOriginPort => _serverList[1].port;

  DispatchingServer? get server => _server;

  /// [startServers] will start two Http servers.
  ///
  /// The first server listens on [port] and sets
  ///   "Access-Control-Allow-Origin: *"
  /// The second server listens on [crossOriginPort] and sets
  ///   "Access-Control-Allow-Origin: client:port1
  ///   "Access-Control-Allow-Credentials: true"
  Future startServers(
    String host, {
    int port = 0,
    int crossOriginPort = 0,
  }) async {
    _packageConfig = await loadPackageConfigUri(Uri.base.resolveUri(_packages));

    _server = await _startHttpServer(host, port: port);
    await _startHttpServer(
      host,
      port: crossOriginPort,
      allowedPort: _serverList[0].port,
    );
  }

  /// Gets the command line string to spawn the server.
  String get commandLine {
    var dart = Platform.resolvedExecutable;
    var script = _dartDirectory.resolve('pkg/test_runner/bin/http_server.dart');
    var buildDirectory = _buildDirectory.toFilePath();

    return [
      dart,
      script.toFilePath(),
      '-p',
      port,
      '-c',
      crossOriginPort,
      '--network',
      network,
      '--build-directory=$buildDirectory',
      '--runtime=${runtime.name}',
      if (useContentSecurityPolicy) '--csp',
      '--packages=${_packages.toFilePath()}',
    ].join(' ');
  }

  void stopServers() {
    for (var server in _serverList) {
      server.close();
    }
  }

  void _onError(Object? e) {
    DebugLogger.error('HttpServer: an error occurred', e);
  }

  Future<DispatchingServer> _startHttpServer(
    String host, {
    int port = 0,
    int allowedPort = -1,
  }) {
    return HttpServer.bind(host, port).then((HttpServer httpServer) {
      var server = DispatchingServer(httpServer, _onError, _sendNotFound);
      server.addHandler('/echo', _handleEchoRequest);
      server.addHandler('/ws', _handleWebSocketRequest);
      fileHandler(HttpRequest request) {
        _handleFileOrDirectoryRequest(request, allowedPort);
      }

      server.addHandler('/$prefixBuildDir', fileHandler);
      server.addHandler('/$prefixDartDir', fileHandler);
      server.addHandler('/packages', fileHandler);
      server.addHandler('/upload', _handleUploadRequest);
      _serverList.add(httpServer);
      return server;
    });
  }

  Future _handleFileOrDirectoryRequest(
    HttpRequest request,
    int allowedPort,
  ) async {
    // Enable browsers to cache file/directory responses.
    var response = request.response;
    response.headers.set("Cache-Control", "max-age=$_cacheExpirationSeconds");
    try {
      var path = _getFileUriFromRequestUri(request.uri);
      if (path != null) {
        var file = File.fromUri(path);
        var directory = Directory.fromUri(path);
        if (await file.exists()) {
          _sendFileContent(request, response, allowedPort, file);
        } else if (await directory.exists()) {
          _sendDirectoryListing(
            await _listDirectory(directory),
            request,
            response,
          );
        } else {
          _sendNotFound(request);
        }
      } else {
        if (request.uri.path == '/') {
          var entries = [
            _Entry('root_dart', 'root_dart/'),
            _Entry('root_build', 'root_build/'),
            _Entry('echo', 'echo'),
          ];
          _sendDirectoryListing(entries, request, response);
        } else {
          _sendNotFound(request);
        }
      }
    } catch (e) {
      _sendNotFound(request);
    }
  }

  void _handleEchoRequest(HttpRequest request) {
    request.response.headers.set("Access-Control-Allow-Origin", "*");
    request.cast<List<int>>().pipe(request.response).catchError((e) {
      DebugLogger.warning(
        'HttpServer: error while closing the response stream',
        e,
      );
    });
  }

  void _handleWebSocketRequest(HttpRequest request) {
    WebSocketTransformer.upgrade(request)
        .then((websocket) {
          // We ignore failures to write to the socket, this happens if the browser
          // closes the connection.
          websocket.done.catchError((_) {});
          websocket.listen(
            (data) {
              websocket.add(data);
              if (data == 'close-with-error') {
                // Note: according to the web-sockets spec, a reason longer than 123
                // bytes will produce a SyntaxError on the client.
                websocket.close(WebSocketStatus.unsupportedData, 'X' * 124);
              } else {
                websocket.close();
              }
            },
            onError: (e) {
              DebugLogger.warning(
                'HttpServer: error while echoing to WebSocket',
                e,
              );
            },
          );
        })
        .catchError((e) {
          DebugLogger.warning(
            'HttpServer: error while transforming to WebSocket',
            e,
          );
        });
  }

  void _handleUploadRequest(HttpRequest request) async {
    try {
      var builder = await request.fold(BytesBuilder(), (dynamic b, d) {
        b.add(d);
        return b;
      });
      var data = builder.takeBytes();
      DebugLogger.info(
        'Uploaded data: ${String.fromCharCodes(data as Iterable<int>)}',
      );
      request.response.headers.set("Access-Control-Allow-Origin", "*");
      request.response.close();
    } catch (e) {
      DebugLogger.warning(
        'HttpServer: error while processing upload request',
        e,
      );
    }
  }

  Uri? _getFileUriFromRequestUri(Uri request) {
    // Go to the top of the file to see an explanation of the URL path scheme.
    var pathSegments = request.normalizePath().pathSegments;
    if (pathSegments.isEmpty) return null;
    var packagesIndex = pathSegments.indexOf('packages');
    if (packagesIndex != -1) {
      var packageUri = Uri(
        scheme: 'package',
        pathSegments: pathSegments.skip(packagesIndex + 1),
      );
      return _packageConfig.resolve(packageUri);
    }
    if (pathSegments[0] == prefixBuildDir) {
      return _buildDirectory.resolve(pathSegments.skip(1).join('/'));
    }
    if (pathSegments[0] == prefixDartDir) {
      return _dartDirectory.resolve(pathSegments.skip(1).join('/'));
    }
    return null;
  }

  Future<List<_Entry>> _listDirectory(Directory directory) {
    var completer = Completer<List<_Entry>>();
    var entries = <_Entry>[];

    directory.list().listen(
      (FileSystemEntity fse) {
        var segments = fse.uri.pathSegments;
        if (fse is File) {
          var filename = segments.last;
          entries.add(_Entry(filename, filename));
        } else if (fse is Directory) {
          var dirname = segments[segments.length - 2];
          entries.add(_Entry(dirname, '$dirname/'));
        }
      },
      onDone: () {
        completer.complete(entries);
      },
    );
    return completer.future;
  }

  void _sendDirectoryListing(
    List<_Entry> entries,
    HttpRequest request,
    HttpResponse response,
  ) {
    response.headers.set('Content-Type', 'text/html');
    var header =
        '''<!DOCTYPE html>
    <html>
    <head>
      <title>${request.uri.path}</title>
      <meta charset="utf-8">
    </head>
    <body>
      <code>
        <div>${request.uri.path}</div>
        <hr/>
        <ul>''';
    var footer = '''
        </ul>
      </code>
    </body>
    </html>''';

    entries.sort();
    response.write(header);
    for (var entry in entries) {
      response.write(
        '<li><a href="${request.uri}/${entry.name}">'
        '${entry.displayName}</a></li>',
      );
    }
    response.write(footer);
    response.close();
    response.done.catchError((e) {
      DebugLogger.warning(
        'HttpServer: error while closing the response stream',
        e,
      );
    });
  }

  void _sendFileContent(
    HttpRequest request,
    HttpResponse response,
    int allowedPort,
    File file,
  ) {
    if (allowedPort != -1) {
      var headerOrigin = request.headers.value('Origin');
      String allowedOrigin;
      if (headerOrigin != null) {
        var origin = Uri.parse(headerOrigin);
        // Allow loading from http://*:$allowedPort in browsers.
        allowedOrigin = '${origin.scheme}://${origin.host}:$allowedPort';
      } else {
        allowedOrigin = '*';
      }

      response.headers.set("Access-Control-Allow-Origin", allowedOrigin);
      response.headers.set('Access-Control-Allow-Credentials', 'true');
    } else {
      // No allowedPort specified. Allow from anywhere (but cross-origin
      // requests *with credentials* will fail because you can't use "*").
      response.headers.set("Access-Control-Allow-Origin", "*");
    }
    if (useContentSecurityPolicy) {
      // Chrome respects the standardized Content-Security-Policy header,
      // whereas Firefox uses X-Content-Security-Policy. Safari still uses the
      // WebKit- prefixed version.
      var contentHeaderValue = [
        "script-src 'self'",
        "object-src 'self'",

        // Trusted types (https://w3c.github.io/trusted-types/dist/spec/#trusted-types-csp-directive)
        //
        // Policy `dart.deferred-loading` is used to trust dart2js's deferred
        // loading URLs, and is tested by tests/web/deferred/trusted_script_url
        //
        // Policy `scriptUrl` is the name of a policy created to test creation
        // of policies via js-interop, and is tested by
        // tests/lib/js/static_interop_test/import/import_trustedscripturl_test
        "require-trusted-types-for: 'script'",
        "trusted-types dart.deferred-loading scriptUrl",
      ].join('; ');
      for (var header in [
        "Content-Security-Policy",
        "X-Content-Security-Policy",
      ]) {
        response.headers.set(header, contentHeaderValue);
      }
      if (runtime == Runtime.safari) {
        response.headers.set("X-WebKit-CSP", contentHeaderValue);
      }
    }
    if (file.path.endsWith('.html')) {
      response.headers.set('Content-Type', 'text/html');
    } else if (file.path.endsWith('.js') || file.path.endsWith('.mjs')) {
      response.headers.set('Content-Type', 'application/javascript');
    } else if (file.path.endsWith('.dart')) {
      response.headers.set('Content-Type', 'application/dart');
    } else if (file.path.endsWith('.css')) {
      response.headers.set('Content-Type', 'text/css');
    } else if (file.path.endsWith('.xml')) {
      response.headers.set('Content-Type', 'text/xml');
    } else if (file.path.endsWith('.wasm')) {
      response.headers.set('Content-Type', 'application/wasm');
    }
    response.headers.removeAll("X-Frame-Options");
    file.openRead().cast<List<int>>().pipe(response).catchError((e) {
      DebugLogger.warning(
        'HttpServer: error while closing the response stream',
        e,
      );
    });
  }

  void _sendNotFound(HttpRequest request) {
    bool isHarmlessPath(String path) {
      return _harmlessRequestPathSuffixes.any((pattern) {
        return path.contains(pattern);
      });
    }

    if (!isHarmlessPath(request.uri.path)) {
      DebugLogger.warning(
        'HttpServer: could not find file for request path: '
        '"${request.uri.path}"',
      );
    }
    var response = request.response;
    response.statusCode = HttpStatus.notFound;

    // Send a nice HTML page detailing the error message.  Most browsers expect
    // this, for example, Chrome will simply display a blank page if you don't
    // provide any information.  A nice side effect of this is to work around
    // Firefox bug 1016313
    // (https://bugzilla.mozilla.org/show_bug.cgi?id=1016313).
    response.headers.set(HttpHeaders.contentTypeHeader, 'text/html');
    var escapedPath = const HtmlEscape().convert(request.uri.path);
    response.write("""
<!DOCTYPE html>
<html lang='en'>
<head>
<title>Not Found</title>
</head>
<body>
<h1>Not Found</h1>
<p style='white-space:pre'>The file '$escapedPath' could not be found.</p>
</body>
</html>
""");
    response.close();
    response.done.catchError((e) {
      DebugLogger.warning(
        'HttpServer: error while closing the response stream',
        e,
      );
    });
  }
}

/// Helper class for displaying directory listings.
class _Entry implements Comparable<_Entry> {
  final String name;
  final String displayName;

  _Entry(this.name, this.displayName);

  @override
  int compareTo(_Entry other) {
    return name.compareTo(other.name);
  }
}
