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

library service_tester;

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';

import 'package:path/path.dart' as path;
import 'package:pedantic/pedantic.dart';
import 'package:test/test.dart';
import 'package:vm_service/vm_service.dart';
import 'package:vm_service/vm_service_io.dart';

final String host = 'localhost';
final int port = 7575;

VmService serviceClient;

void main() {
  Process process;

  tearDown(() {
    process?.kill();
  });

  test('integration', () async {
    String sdk = path.dirname(path.dirname(Platform.resolvedExecutable));

    print('Using sdk at ${sdk}.');

    // pause_isolates_on_start, pause_isolates_on_exit
    process = await Process.start('${sdk}/bin/dart', [
      '--pause_isolates_on_start',
      '--enable-vm-service=${port}',
      '--disable-service-auth-codes',
      'example/sample_main.dart'
    ]);

    print('dart process started');

    // ignore: unawaited_futures
    process.exitCode.then((code) => print('vm exited: ${code}'));
    // ignore: strong_mode_down_cast_composite
    process.stdout.transform(utf8.decoder).listen(print);
    // ignore: strong_mode_down_cast_composite
    process.stderr.transform(utf8.decoder).listen(print);

    await Future.delayed(Duration(milliseconds: 500));

    // ignore: deprecated_member_use_from_same_package
    serviceClient = await vmServiceConnect(host, port, log: StdoutLog());

    print('socket connected');

    serviceClient.onSend.listen((str) => print('--> ${str}'));

    // The next listener will bail out if you toggle this to false, which we need
    // to do for some things like the custom service registration tests.
    var checkResponseJsonCompatibility = true;
    serviceClient.onReceive.listen((str) {
      print('<-- ${str}');

      if (!checkResponseJsonCompatibility) return;

      // For each received event, check that we can deserialize it and
      // reserialize it back to the same exact representation (minus private
      // fields).
      var json = jsonDecode(str);
      var originalJson = json['result'] as Map<String, dynamic>;
      if (originalJson == null && json['method'] == 'streamNotify') {
        originalJson = json['params']['event'];
      }
      expect(originalJson, isNotNull, reason: 'Unrecognized event type! $json');

      // ignore: invalid_use_of_visible_for_testing_member
      var instance =
          createServiceObject(originalJson, const ['Event', 'Success']);
      expect(instance, isNotNull,
          reason: 'failed to deserialize object $originalJson!');

      var reserializedJson = (instance as dynamic).toJson();

      forEachNestedMap(originalJson, (obj) {
        // Private fields that we don't reproduce
        obj.removeWhere((k, v) => k.startsWith('_'));
        // Extra fields that aren't specified and we don't reproduce
        obj.remove('isExport');
      });

      forEachNestedMap(reserializedJson, (obj) {
        // We provide explicit defaults for these, need to remove them.
        obj.remove('valueAsStringIsTruncated');
      });

      expect(reserializedJson, equals(originalJson));
    });

    serviceClient.onIsolateEvent.listen((e) => print('onIsolateEvent: ${e}'));
    serviceClient.onDebugEvent.listen((e) => print('onDebugEvent: ${e}'));
    serviceClient.onGCEvent.listen((e) => print('onGCEvent: ${e}'));
    serviceClient.onStdoutEvent.listen((e) => print('onStdoutEvent: ${e}'));
    serviceClient.onStderrEvent.listen((e) => print('onStderrEvent: ${e}'));

    unawaited(serviceClient.streamListen(EventStreams.kIsolate));
    unawaited(serviceClient.streamListen(EventStreams.kDebug));
    unawaited(serviceClient.streamListen(EventStreams.kStdout));

    VM vm = await serviceClient.getVM();
    print('hostCPU=${vm.hostCPU}');
    print(await serviceClient.getVersion());
    List<IsolateRef> isolates = await vm.isolates;
    print(isolates);

    // Disable the json reserialization checks since custom services are not
    // supported.
    checkResponseJsonCompatibility = false;
    await testServiceRegistration();
    checkResponseJsonCompatibility = true;

    await testScriptParse(vm.isolates.first);
    await testSourceReport(vm.isolates.first);

    IsolateRef isolateRef = isolates.first;
    print(await serviceClient.resume(isolateRef.id));

    print('waiting for client to shut down...');
    serviceClient.dispose();

    await serviceClient.onDone;
    print('service client shut down');
  });
}

// Deeply traverses a map and calls [cb] with each nested map and the
// parent map.
void forEachNestedMap(Map input, Function(Map) cb) {
  var queue = Queue.from([input]);
  while (queue.isNotEmpty) {
    var next = queue.removeFirst();
    if (next is Map) {
      cb(next);
      queue.addAll(next.values);
    } else if (next is List) {
      queue.addAll(next);
    }
  }
}

Future testServiceRegistration() async {
  const String serviceName = 'serviceName';
  const String serviceAlias = 'serviceAlias';
  const String movedValue = 'movedValue';
  serviceClient.registerServiceCallback(serviceName,
      (Map<String, dynamic> params) async {
    assert(params['input'] == movedValue);
    return <String, dynamic>{
      'result': {'output': params['input']}
    };
  });
  await serviceClient.registerService(serviceName, serviceAlias);
  VmService otherClient =
      // ignore: deprecated_member_use_from_same_package
      await vmServiceConnect(host, port, log: StdoutLog());
  Completer completer = Completer();
  otherClient.onEvent('Service').listen((e) async {
    if (e.service == serviceName && e.kind == EventKind.kServiceRegistered) {
      assert(e.alias == serviceAlias);
      Response response = await serviceClient.callMethod(
        e.method,
        args: <String, dynamic>{'input': movedValue},
      );
      assert(response.json['output'] == movedValue);
      completer.complete();
    }
  });
  await otherClient.streamListen('Service');
  await completer.future;
  otherClient.dispose();
}

Future testScriptParse(IsolateRef isolateRef) async {
  final Isolate isolate = await serviceClient.getIsolate(isolateRef.id);
  final Library rootLibrary =
      await serviceClient.getObject(isolateRef.id, isolate.rootLib.id);
  final ScriptRef scriptRef = rootLibrary.scripts.first;

  final Script script =
      await serviceClient.getObject(isolateRef.id, scriptRef.id);
  print(script);
  print(script.uri);
  print(script.library);
  print(script.source.length);
  print(script.tokenPosTable.length);
}

Future testSourceReport(IsolateRef isolateRef) async {
  final Isolate isolate = await serviceClient.getIsolate(isolateRef.id);
  final Library rootLibrary =
      await serviceClient.getObject(isolateRef.id, isolate.rootLib.id);
  final ScriptRef scriptRef = rootLibrary.scripts.first;

  // make sure some code has run
  await serviceClient.resume(isolateRef.id);
  await Future.delayed(const Duration(milliseconds: 25));

  final SourceReport sourceReport = await serviceClient.getSourceReport(
      isolateRef.id, [SourceReportKind.kCoverage],
      scriptId: scriptRef.id);
  for (SourceReportRange range in sourceReport.ranges) {
    print('  $range');
    if (range.coverage != null) {
      print('  ${range.coverage}');
    }
  }
  print(sourceReport);
}

class StdoutLog extends Log {
  void warning(String message) => print(message);

  void severe(String message) => print(message);
}
