// Copyright (c) 2019, 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=--enable-isolate-groups --experimental-enable-isolate-groups-jit
// VMOptions=--no-enable-isolate-groups

import 'dart:async';
import 'dart:io';
import 'dart:isolate';

import 'package:http/http.dart' as http;

void main() async {
  // Start a server to obtain a randomly assigned, free port.
  final mainServer = await HttpServer.bind('::1', 0, shared: true);
  final sharedPort = mainServer.port;

  final workers =
      List<ServerWorker>.generate(4, (i) => ServerWorker(i, sharedPort));
  await Future.wait(workers.map((w) => w.start()));
  mainServer.close();

  await Future.delayed(Duration(seconds: 1));
  // spawn client isolate
  final clientisolate = await Isolate.spawn(client, sharedPort);
  // Wait for 20 secs. It used to crash within 10 seconds.
  await Future.delayed(Duration(seconds: 20));

  workers.forEach((w) {
    w.respawn = false;
    w.terminate();
  });
  print('kill client isolates');
  clientisolate.kill();
}

class ServerWorker {
  final int workerid;
  final int port;
  Isolate? _isolate;
  bool respawn = true;

  ServerWorker(this.workerid, this.port);

  Future<void> start() async {
    final onExit = ReceivePort();
    onExit.listen((_) {
      onExit.close();
      // Respawn another isolate
      if (respawn) start();
    });
    final ready = ReceivePort();
    _isolate = await Isolate.spawn(_main, [workerid, port, ready.sendPort],
        errorsAreFatal: true, onExit: onExit.sendPort);
    await ready.first;
    if (workerid == 0) terminate();
  }

  void terminate() {
    Future.delayed(Duration(seconds: 1), () {
      print('terminate ${workerid}');
      _isolate?.kill();
      _isolate = null;
    });
  }

  static _main(List args) async {
    final workerid = args[0] as int;
    final port = args[1] as int;
    final readyPort = args[2] as SendPort;

    final server = await HttpServer.bind('::1', port, shared: true);
    readyPort.send(null);
    server.listen((HttpRequest request) {
      print('from worker ${workerid}');
      final response = request.response;
      response.statusCode = HttpStatus.ok;
      response.write('server worker ${workerid}');
      response.close();
    });
  }
}

Future<String> get(Uri url) async {
  while (true) {
    try {
      await http.get(url);
      return '';
    } catch (err) {}
  }
}

void client(int port) async {
  while (true) {
    final futures = <Future>[];
    final numAtOnce = 16; // enough to keep the server busy
    for (int i = 0; i < numAtOnce; ++i) {
      futures.add(get(Uri.http('localhost:$port', '')).then((_) {}));
    }
    await Future.wait(futures);
  }
}
