// Copyright (c) 2022, 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:io';

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

import 'common/test_helper.dart';
import 'post_event_custom_stream_script.dart' as script;

void main() {
  late Process process;
  late DartDevelopmentService dds;

  setUp(() async {
    process = await spawnDartProcess(
      'post_event_custom_stream_script.dart',
    );
  });

  tearDown(() async {
    await dds.shutdown();
    process.kill();
  });

  Future<IsolateRef> getIsolate(VmService service) async {
    IsolateRef isolate;
    while (true) {
      final vm = await service.getVM();
      if (vm.isolates!.isNotEmpty) {
        isolate = vm.isolates!.first;
        break;
      }
      await Future.delayed(const Duration(milliseconds: 50));
    }
    return isolate;
  }

  test('sends a postEvent over a custom stream to multiple listeners',
      () async {
    dds = await DartDevelopmentService.startDartDevelopmentService(
      remoteVmServiceUri,
    );
    expect(dds.isRunning, true);

    final service1 = await vmServiceConnectUri(dds.wsUri.toString());
    final service2 = await vmServiceConnectUri(dds.wsUri.toString());
    final completer1 = Completer<Event>();
    final completer2 = Completer<Event>();
    final isolateId = (await getIsolate(service1)).id!;

    await service1.streamListen(script.customStreamId);
    service1.onEvent(script.customStreamId).listen((event) {
      completer1.complete(event);
    });
    await service2.streamListen(script.customStreamId);
    service2.onEvent(script.customStreamId).listen((event) {
      completer2.complete(event);
    });

    await service1.resume(isolateId);

    final event1 = await completer1.future;
    final event2 = await completer2.future;

    expect(event1.extensionKind, equals(script.eventKind));
    expect(event1.extensionData?.data, equals(script.eventData));

    expect(event2.extensionKind, equals(script.eventKind));
    expect(event2.extensionData?.data, equals(script.eventData));
  });

  test('can cancel custom stream listeners', () async {
    dds = await DartDevelopmentService.startDartDevelopmentService(
      remoteVmServiceUri,
    );
    expect(dds.isRunning, true);
    final service1 = await vmServiceConnectUri(dds.wsUri.toString());
    (await getIsolate(service1)).id!;

    await service1.streamListen(script.customStreamId);

    // We should be able to cancel
    await service1.streamCancel(script.customStreamId);

    try {
      await service1.streamCancel(script.customStreamId);
      fail('Re-Canceling the custom stream should have failed');
    } on RPCError catch (e) {
      expect(
        e.message,
        'Stream not subscribed',
      );
    }
  });

  test('canceling a custom stream does not cancel other listeners', () async {
    dds = await DartDevelopmentService.startDartDevelopmentService(
      remoteVmServiceUri,
    );
    expect(dds.isRunning, true);
    final service1 = await vmServiceConnectUri(dds.wsUri.toString());
    final isolateId = (await getIsolate(service1)).id!;
    final extensionCompleter = Completer<Event>();

    await service1.streamListen(script.customStreamId);
    await service1.streamListen('Extension');
    service1.onEvent('Extension').listen((event) {
      extensionCompleter.complete(event);
    });

    await service1.streamCancel(script.customStreamId);

    await service1.resume(isolateId);

    final event1 = await extensionCompleter.future;

    expect(event1.extensionKind, equals(script.eventKind));
    expect(event1.extensionData?.data, equals(script.eventData));
  });

  test('Canceling a normal stream does not cancel custom listeners', () async {
    dds = await DartDevelopmentService.startDartDevelopmentService(
      remoteVmServiceUri,
    );
    expect(dds.isRunning, true);
    final service1 = await vmServiceConnectUri(dds.wsUri.toString());
    final isolateId = (await getIsolate(service1)).id!;
    final customStreamCompleter = Completer<Event>();

    await service1.streamListen(script.customStreamId);
    await service1.streamListen('Extension');
    service1.onEvent(script.customStreamId).listen((event) {
      customStreamCompleter.complete(event);
    });

    await service1.streamCancel('Extension');

    await service1.resume(isolateId);

    final event1 = await customStreamCompleter.future;

    expect(event1.extensionKind, equals(script.eventKind));
    expect(event1.extensionData?.data, equals(script.eventData));
  });
}
