// Copyright (c) 2021, 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=--verbose_debug --enable-isolate-groups
//
// Tests breakpoint pausing and resuming with many isolates running and pausing
// simultaneously.

import 'dart:async';
import 'dart:developer';
import 'dart:isolate' as dart_isolate;

import 'package:observatory_2/service_io.dart';
import 'package:test/test.dart';

import 'service_test_common.dart';
import 'test_helper.dart';

const int LINE_A = 23;
const int LINE_B = 35;
const int LINE_C = 41;

foo(args) { // LINE_A
  print('${dart_isolate.Isolate.current.debugName}: $args');
  final sendPort = args[0] as dart_isolate.SendPort;
  final int i = args[1] as int;
  sendPort.send('reply from foo: $i');
}

int nIsolates = -1;

testMain() async {
  final rps = List<dart_isolate.ReceivePort>.generate(
      nIsolates, (i) => dart_isolate.ReceivePort());
  debugger(); // LINE_B
  for (int i = 0; i < nIsolates; i++) {
    await dart_isolate.Isolate.spawn(foo, [rps[i].sendPort, i],
        debugName: "foo$i");
  }
  print(await Future.wait(rps.map((rp) => rp.first)));
  debugger(); // LINE_C
}

final completerAtFoo = List<Completer>.generate(nIsolates, (_) => Completer());
int completerCount = 0;

final tests = <IsolateTest>[
  hasPausedAtStart,
  resumeIsolate,
  hasStoppedAtBreakpoint,
  stoppedAtLine(LINE_B + 1),
  (Isolate isolate) async {
    // Set up a listener to wait for child isolate launch and breakpoint events.
    final stream = await isolate.vm.getEventStream(VM.kDebugStream);
    var subscription;
    subscription = stream.listen((ServiceEvent event) async {
      switch (event.kind) {
        case ServiceEvent.kPauseStart:
          final childIsolate = event.isolate;
          await childIsolate.reload();

          for (Library lib in childIsolate.libraries) {
            await lib.load();
            if (lib.uri
                .endsWith('break_on_function_many_child_isolates_test.dart')) {
              final foo = lib.functions.singleWhere((f) => f.name == 'foo');
              final bpt = await childIsolate.addBreakpointAtEntry(foo);

              expect(bpt is Breakpoint, isTrue);
              break;
            }
          }
          childIsolate.resume();
          break;
        case ServiceEvent.kPauseBreakpoint:
          final name = event.isolate.name;
          if (!name.startsWith('foo')) {
            break;
          }
          final childIsolate = event.isolate;
          final ndx = int.parse(name.substring('foo'.length));
          final stack = await childIsolate.getStack();
          final top = stack['frames'][0];
          final script = await top.location.script.load() as Script;
          expect(script.tokenToLine(top.location.tokenPos), equals(LINE_A));

          childIsolate.resume();
          if ((++completerCount) == nIsolates) {
            subscription.cancel();
          }
          completerAtFoo[ndx].complete();
          break;
      }
    });
  },
  resumeIsolate,
  (Isolate isolate) async {
    await Future.wait(completerAtFoo.map((c) => c.future));
  },
  hasStoppedAtBreakpoint,
  stoppedAtLine(LINE_C + 1),
  resumeIsolate,
];

Future runIsolateBreakpointPauseTest(args, nIsolates_) {
  nIsolates = nIsolates_;
  return runIsolateTests(args, tests,
      testeeConcurrent: testMain, pause_on_start: true);
}

main(args) async {
  await runIsolateBreakpointPauseTest(args, /*nIsolates=*/ 30);
}
