// 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.
// VMOptions=
// VMOptions=--short_socket_read
// VMOptions=--short_socket_write
// VMOptions=--short_socket_read --short_socket_write
// OtherResources=http_launch_data/http_isolate_main.dart
// OtherResources=http_launch_data/http_launch_main.dart
// OtherResources=http_launch_data/http_spawn_main.dart
// OtherResources=http_launch_data/the_packages/simple/simple.dart
// OtherResources=http_launch_data/.dart_tool/package_config.json
// OtherResources=http_launch_data/.packages
//
// Test:
//   *) Launching a script fetched over HTTP.
//   *) Importing a library fetched over HTTP.
//   *) Automatically resolving package_root when script is fetched over HTTP.
//   *) Spawning a URI over HTTP.

library http_launch_test;

import 'dart:async';
import 'dart:io';
import 'package:expect/expect.dart';

String pathToExecutable = Platform.executable;
List<String> executableArguments = Platform.executableArguments
    .where((arg) => !arg.startsWith('--packages='))
    .toList();
Uri pathOfData = Platform.script.resolve('http_launch_data/');
late int port;

_sendNotFound(HttpResponse response) {
  response.statusCode = HttpStatus.notFound;
  response.close();
}

handleRequest(HttpRequest request) {
  final String path = request.uri.path.substring(1);
  final Uri requestPath = pathOfData.resolve(path);
  final File file = new File(requestPath.toFilePath());
  file.exists().then((bool found) {
    if (found) {
      file.openRead().cast<List<int>>().pipe(request.response).catchError((e) {
        _sendNotFound(request.response);
      });
    } else {
      _sendNotFound(request.response);
    }
  });
}

serverRunning(HttpServer server) {
  port = server.port;
  server.listen(handleRequest);
  Future<ProcessResult> no_http_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..add(pathOfData.resolve('http_launch_main.dart').toFilePath()));
  Future<ProcessResult> http_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..add('http://127.0.0.1:$port/http_launch_main.dart'));
  Future<ProcessResult> http_pkg_root_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..addAll(['http://127.0.0.1:$port/http_launch_main.dart']));
  Future<ProcessResult> isolate_run = Process.run(
      pathToExecutable,
      []
        ..add('--verbosity=warning')
        ..addAll(executableArguments)
        ..addAll(['http://127.0.0.1:$port/http_spawn_main.dart', '$port']));
  Future<List<ProcessResult>> results =
      Future.wait([no_http_run, http_run, http_pkg_root_run, isolate_run]);
  results.then((results) {
    // Close server.
    server.close();
    // Check results.
    checkResults(results);
  });
}

checkResults(List<ProcessResult> results) {
  Expect.equals(4, results.length);
  // Exited cleanly.
  for (int i = 0; i < results.length; i++) {
    ProcessResult result = results[i];
    if (result.exitCode != 0) {
      print("Exit code for process $i = ${result.exitCode}");
      print("---stdout:---\n${result.stdout}");
      print("---stderr:---\n${result.stderr}\n---");
    }
    Expect.equals(0, result.exitCode);
  }
  String stdout = results[0].stdout;
  // Output is the string 'hello'. Use startsWith to avoid new line differences.
  if (!stdout.startsWith('hello')) {
    print("---- stdout of remote process:\n$stdout\n----");
  }
  Expect.isTrue(stdout.startsWith('hello'));
  // Same output from all three process runs.
  for (int i = 0; i < results.length; i++) {
    Expect.equals(stdout, results[i].stdout);
  }
}

main() {
  HttpServer.bind(InternetAddress.loopbackIPv4, 0).then(serverRunning);
}
