// Copyright (c) 2023, 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:developer';
// ignore: library_prefixes
import 'dart:isolate' as I;

import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

import 'common/service_test_common.dart';
import 'common/test_helper.dart';

// AUTOGENERATED START
//
// Update these constants by running:
//
// dart pkg/vm_service/test/update_line_numbers.dart pkg/vm_service/test/isolate_lifecycle_test.dart
//
const LINE_A = 32;
// AUTOGENERATED END

final spawnCount = 4;
final resumeCount = spawnCount ~/ 2;
final isolates = [];

void spawnEntry(int i) {}

Future<void> during() async {
  debugger(); // LINE_A
  // Spawn spawnCount long lived isolates.
  for (int i = 0; i < spawnCount; i++) {
    final isolate = await I.Isolate.spawn(spawnEntry, i);
    isolates.add(isolate);
  }
  print('spawned all isolates');
}

Future<int> numPaused(VmService service) async {
  final vm = await service.getVM();
  int paused = 0;
  for (final isolateRef in vm.isolates!) {
    final isolate = await service.getIsolate(isolateRef.id!);
    if (isolate.pauseEvent != null &&
        isolate.pauseEvent!.kind == EventKind.kPauseExit) {
      paused++;
    }
  }
  return paused;
}

final tests = <VMTest>[
  (VmService service) async {
    final vm = await service.getVM();
    final isolates = vm.isolates!;
    expect(isolates.length, 1);
    await hasStoppedAtBreakpoint(service, isolates[0]);
    await stoppedAtLine(LINE_A)(service, isolates[0]);
  },
  (VmService service) async {
    int startCount = 0;
    int runnableCount = 0;

    final completer = Completer<void>();
    late final StreamSubscription sub;
    sub = service.onIsolateEvent.listen((event) async {
      if (event.kind == EventKind.kIsolateStart) {
        startCount++;
      }
      if (event.kind == EventKind.kIsolateRunnable) {
        runnableCount++;
      }
      if (runnableCount == spawnCount) {
        await sub.cancel();
        await service.streamCancel(EventStreams.kIsolate);
        completer.complete();
      }
    });
    await service.streamListen(EventStreams.kIsolate);

    VM vm = await service.getVM();
    expect(vm.isolates!.length, 1);

    // Resume and wait for the isolates to spawn.
    await service.resume(vm.isolates![0].id!);
    await completer.future;
    expect(startCount, spawnCount);
    expect(runnableCount, spawnCount);
    vm = await service.getVM();
    expect(vm.isolates!.length, spawnCount + 1);
  },
  (VmService service) async {
    final completer = Completer<void>();
    if (await numPaused(service) < (spawnCount + 1)) {
      late final StreamSubscription sub;
      sub = service.onDebugEvent.listen((event) async {
        if (event.kind == EventKind.kPauseExit) {
          if (await numPaused(service) == (spawnCount + 1)) {
            await sub.cancel();
            await service.streamCancel(EventStreams.kDebug);
            completer.complete();
          }
        }
      });
      await service.streamListen(EventStreams.kDebug);
      await completer.future;
    }
    expect(await numPaused(service), spawnCount + 1);
  },
  (VmService service) async {
    int resumedReceived = 0;
    final completer = Completer<void>();
    late final StreamSubscription sub;
    sub = service.onIsolateEvent.listen((event) async {
      if (event.kind == EventKind.kIsolateExit) {
        resumedReceived++;
        if (resumedReceived >= resumeCount) {
          await sub.cancel();
          await service.streamCancel(EventStreams.kIsolate);
          completer.complete();
        }
      }
    });
    await service.streamListen(EventStreams.kIsolate);

    // Resume a subset of the isolates.
    int resumesIssued = 0;

    final vm = await service.getVM();
    final isolateList = vm.isolates!;
    for (final isolate in isolateList) {
      if (isolate.name!.endsWith('main')) {
        continue;
      }
      try {
        resumesIssued++;
        await service.resume(isolate.id!);
      } catch (_) {}
      if (resumesIssued == resumeCount) {
        break;
      }
    }
    await completer.future;
  },
  (VmService service) async {
    expect(await numPaused(service), spawnCount + 1 - resumeCount);
  },
];

void main([args = const <String>[]]) => runVMTests(
      args,
      tests,
      'isolate_lifecycle_test.dart',
      testeeConcurrent: during,
      pauseOnExit: true,
    );
