// Copyright (c) 2015, 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 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';

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

Future<ServiceExtensionResponse> handler(String method, Map parameters) {
  print('Invoked extension: $method');
  switch (method) {
    case 'ext..delay':
      final c = Completer<ServiceExtensionResponse>();
      Timer(Duration(seconds: 1), () {
        c.complete(
          ServiceExtensionResponse.result(
            jsonEncode({
              'type': '_delayedType',
              'method': method,
              'parameters': parameters,
            }),
          ),
        );
      });
      return c.future;
    case 'ext..error':
      return Future<ServiceExtensionResponse>.value(
        ServiceExtensionResponse.error(
          ServiceExtensionResponse.extensionErrorMin,
          'My error detail.',
        ),
      );
    case 'ext..exception':
      throw 'I always throw!';
    case 'ext..success':
      return Future<ServiceExtensionResponse>.value(
        ServiceExtensionResponse.result(
          jsonEncode({
            'type': '_extensionType',
            'method': method,
            'parameters': parameters,
          }),
        ),
      );
  }
  throw 'Unknown extension: $method';
}

void test() {
  registerExtension('ext..delay', handler);
  debugger();
  postEvent('ALPHA', {'cat': 'dog'});
  debugger();
  registerExtension('ext..error', handler);
  registerExtension('ext..exception', handler);
  registerExtension('ext..success', handler);
  bool exceptionThrown = false;
  try {
    registerExtension('ext..delay', handler);
  } catch (e) {
    exceptionThrown = true;
  }
  // This check is running in the target process so we can't used package:test.
  Expect.equals(exceptionThrown, true);
}

var tests = <IsolateTest>[
  hasStoppedAtBreakpoint,
  (VmService service, IsolateRef isolateRef) async {
    final isolate = await service.getIsolate(isolateRef.id!);
    // Note: extensions other than those is this test might already be
    // registered by core libraries.
    expect(isolate.extensionRPCs, contains('ext..delay'));
    expect(isolate.extensionRPCs, isNot(contains('ext..error')));
    expect(isolate.extensionRPCs, isNot(contains('ext..exception')));
    expect(isolate.extensionRPCs, isNot(contains('ext..success')));
  },
  resumeIsolateAndAwaitEvent(EventStreams.kExtension, (event) {
    expect(event.kind, EventKind.kExtension);
    expect(event.extensionKind, 'ALPHA');
    expect(event.extensionData!.data['cat'], equals('dog'));
  }),
  hasStoppedAtBreakpoint,
  resumeIsolateAndAwaitEvent(EventStreams.kIsolate, (event) {
    // Check that we received an event when '__error' was registered.
    expect(event.kind, equals(EventKind.kServiceExtensionAdded));
    expect(event.extensionRPC, 'ext..error');
  }),
  // Initial.
  (VmService service, IsolateRef isolateRef) async {
    final isolateId = isolateRef.id!;
    var result = await service.callServiceExtension(
      'ext..delay',
      isolateId: isolateId,
    );

    expect(result.json!['type'], '_delayedType');
    expect(result.json!['method'], equals('ext..delay'));
    expect(result.json!['parameters']['isolateId'], isNotNull);

    try {
      await service.callServiceExtension(
        'ext..error',
        isolateId: isolateId,
      );
    } on RPCError catch (e) {
      expect(e.code, ServiceExtensionResponse.extensionErrorMin);
      expect(e.details, 'My error detail.');
    }

    try {
      await service.callServiceExtension(
        'ext..exception',
        isolateId: isolateId,
      );
    } on RPCError catch (e) {
      expect(e.code, ServiceExtensionResponse.extensionError);
      expect(e.details!.startsWith('I always throw!\n'), isTrue);
    }

    result = await service.callServiceExtension(
      'ext..success',
      isolateId: isolateId,
      args: {
        'apple': 'banana',
      },
    );
    expect(result.json!['type'], '_extensionType');
    expect(result.json!['method'], 'ext..success');
    expect(result.json!['parameters']['isolateId'], isNotNull);
    expect(result.json!['parameters']['apple'], 'banana');
  },
];

void main([args = const <String>[]]) => runIsolateTests(
      args,
      tests,
      'developer_extension_test.dart',
      testeeConcurrent: test,
    );
