// 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.

import 'dart:async';
import 'dart:convert';
import 'dart:developer';
import 'dart:io' as io;

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

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

const String content = 'some random content';
const String udpContent = 'aghfkjdb';
const String kClearSocketProfileRPC = 'ext.dart.io.clearSocketProfile';
const String kGetSocketProfileRPC = 'ext.dart.io.getSocketProfile';
const String kGetVersionRPC = 'ext.dart.io.getVersion';
const String kPauseSocketProfilingRPC = 'ext.dart.io.pauseSocketProfiling';
const String kStartSocketProfilingRPC = 'ext.dart.io.startSocketProfiling';
const String kSocketProfilingEnabledRPC = 'ext.dart.io.socketProfilingEnabled';
const String localhost = '127.0.0.1';

Future<void> waitForStreamEvent(
    VmService service, IsolateRef isolateRef, bool state,
    {bool useSetter = true}) async {
  final completer = Completer<void>();
  final isolateId = isolateRef.id;
  late StreamSubscription sub;
  sub = service.onExtensionEvent.listen((event) {
    expect(event.extensionKind, 'SocketProfilingStateChange');
    expect(event.extensionData!.data['isolateId'], isolateRef.id);
    expect(event.extensionData!.data['enabled'], state);
    sub.cancel();
    completer.complete();
  });
  await service.streamListen(EventStreams.kExtension);

  if (useSetter) {
    state
        // ignore: deprecated_member_use_from_same_package
        ? await service.startSocketProfiling(isolateId)
        // ignore: deprecated_member_use_from_same_package
        : await service.pauseSocketProfiling(isolateId);
  } else {
    await service.socketProfilingEnabled(isolateId, state);
  }
  await completer.future;
  await service.streamCancel(EventStreams.kExtension);
}

Future<void> setup() async {}

Future<void> socketTest() async {
  // Socket
  var serverSocket = await io.ServerSocket.bind(localhost, 0);
  var socket = await io.Socket.connect(localhost, serverSocket.port);
  socket.write(content);
  await socket.flush();
  socket.destroy();

  // rawDatagram
  final doneCompleter = Completer<void>();
  var server = await io.RawDatagramSocket.bind(localhost, 0);
  server.listen((io.RawSocketEvent event) {
    if (event == io.RawSocketEvent.read) {
      server.receive();
      if (!doneCompleter.isCompleted) {
        doneCompleter.complete();
      }
    }
  });
  var client = await io.RawDatagramSocket.bind(localhost, 0);
  client.send(utf8.encoder.convert(udpContent), io.InternetAddress(localhost),
      server.port);
  client.send([1, 2, 3], io.InternetAddress(localhost), server.port);

  // Wait for datagram to arrive.
  await doneCompleter.future;
  // Post finish event
  postEvent('socketTest', {'socket': 'test'});
}

var tests = <IsolateTest>[
  (VmService service, IsolateRef isolateRef) async {
    final isolate = await service.getIsolate(isolateRef.id);
    // Ensure all network profiling service extensions are registered.
    expect(isolate.extensionRPCs!.length, greaterThanOrEqualTo(5));
    expect(isolate.extensionRPCs!.contains(kClearSocketProfileRPC), isTrue);
    expect(isolate.extensionRPCs!.contains(kGetVersionRPC), isTrue);
    expect(isolate.extensionRPCs!.contains(kPauseSocketProfilingRPC), isTrue);
    expect(isolate.extensionRPCs!.contains(kStartSocketProfilingRPC), isTrue);
    expect(isolate.extensionRPCs!.contains(kPauseSocketProfilingRPC), isTrue);
    expect(isolate.extensionRPCs!.contains(kSocketProfilingEnabledRPC), isTrue);
  },

  // Test getSocketProfiler
  (VmService service, IsolateRef isolateRef) async {
    final socketProfile = await service.getSocketProfile(isolateRef.id);
    expect(socketProfile.sockets.isEmpty, isTrue);
  },
  // Exercise methods naively
  (VmService service, IsolateRef isolateRef) async {
    final version = await service.getDartIOVersion(isolateRef.id);
    expect(version.major >= 1, true);
    expect(version.minor >= 0, true);
    await service.clearSocketProfile(isolateRef.id);
    await service.getSocketProfile(isolateRef.id);
  },
  (VmService service, IsolateRef isolateRef) async {
    final initial =
        (await service.socketProfilingEnabled(isolateRef.id)).enabled;
    await waitForStreamEvent(service, isolateRef, !initial);
    expect((await service.socketProfilingEnabled(isolateRef.id)).enabled,
        !initial);
    await waitForStreamEvent(service, isolateRef, initial);
    expect(
        (await service.socketProfilingEnabled(isolateRef.id)).enabled, initial);
  },
  (VmService service, IsolateRef isolateRef) async {
    final initial =
        (await service.socketProfilingEnabled(isolateRef.id)).enabled;
    await waitForStreamEvent(service, isolateRef, !initial, useSetter: false);
    expect((await service.socketProfilingEnabled(isolateRef.id)).enabled,
        !initial);
    await waitForStreamEvent(service, isolateRef, initial, useSetter: false);
    expect(
        (await service.socketProfilingEnabled(isolateRef.id)).enabled, initial);
  }
  // TODO(bkonyi): fully port observatory test for socket profiling.
];

main([args = const <String>[]]) async =>
    runIsolateTests(args, tests, testeeBefore: setup);
