// 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 new Future.delayed(new Duration(milliseconds: 500));

    // ignore: deprecated_member_use_from_same_package
    serviceClient = await vmServiceConnect(host, port, log: new 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: new StdoutLog());
  Completer completer = new 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);
}
