// 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.
// VMOptions=--verbose-debug

import 'dart:async';

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/regress_46419_test.dart
//
const LINE_A = 31;
const LINE_B = 34;
const LINE_C = 41;
const LINE_D = 48;
// AUTOGENERATED END

// DO NOT REORDER BEYOND THIS POINT
bool testing = false;
void printSync() {
  print('sync');
  if (testing) {
    // LINE_A
    // We'll never reach this code, but setting a breakpoint here will result in
    // the breakpoint being resolved below at line LINE_C.
    print('unreachable'); // LINE_B
  }
}

Iterable<void> printSyncStar() sync* {
  // We'll end up resolving breakpoint 1 to this location instead of at LINE_A
  // if #46419 regresses.
  print('sync*'); // LINE_C
}

void testeeDo() {
  printSync();
  final iterator = printSyncStar();

  print('middle'); // LINE_D

  iterator.toList();
}
// END DO NOT REORDER SECTION

late Breakpoint bp1;
late Breakpoint bp2;

final tests = <IsolateTest>[
  hasPausedAtStart,
  (VmService service, IsolateRef isolateRef) async {
    final isolateId = isolateRef.id!;
    final isolate = await service.getIsolate(isolateId);
    final rootLib = await service.getObject(
      isolateId,
      isolate.rootLib!.id!,
    ) as Library;
    final scriptId = rootLib.scripts!.first.id!;

    bp1 = await service.addBreakpoint(isolateId, scriptId, LINE_B);
    print('BP1 - $bp1');
    bp2 = await service.addBreakpoint(isolateId, scriptId, LINE_D);
    print('BP2 - $bp2');

    final done = Completer<void>();
    late final StreamSubscription sub;
    sub = service.onDebugEvent.listen((event) async {
      if (event.kind == EventKind.kPauseBreakpoint) {
        expect(event.pauseBreakpoints!.length, 1);
        final bp = event.pauseBreakpoints!.first;
        print('Hit $bp');
        expect(bp, bp2);
        await sub.cancel();
        await service.streamCancel(EventStreams.kDebug);
        await service.resume(isolateId);
        done.complete();
      }
    });
    await service.streamListen(EventStreams.kDebug);
    await service.resume(isolateId);
    await done.future;
  }
];

void main([args = const <String>[]]) => runIsolateTests(
      args,
      tests,
      'regress_46419_test.dart',
      testeeConcurrent: testeeDo,
      pauseOnStart: true,
    );
