// Copyright (c) 2020, 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.

// @dart = 2.9

import "dart:io";

import "vm_service_helper.dart" as vmService;

class Foo {
  final String x;
  final int y;

  Foo(this.x, this.y);
}

Future<void> main(List<String> args) async {
  String connectTo;
  String classToFind;
  String whatToDo;
  for (String arg in args) {
    if (arg.startsWith("--url=")) {
      connectTo = arg.substring("--url=".length);
    } else if (arg.startsWith("--find=")) {
      classToFind = arg.substring("--find=".length);
    } else if (arg.startsWith("--action=")) {
      whatToDo = arg.substring("--action=".length);
    }
  }
  List<Foo> foos = [];
  foos.add(new Foo("hello", 42));
  foos.add(new Foo("world", 43));
  foos.add(new Foo("!", 44));

  if (connectTo == null) connectTo = ask("Connect to");
  VMServiceHeapHelperPrinter vm = VMServiceHeapHelperPrinter();
  await vm.connect(Uri.parse(connectTo.trim()));
  String isolateId = await vm.getIsolateId();
  if (classToFind == null) classToFind = ask("Find what class");

  if (whatToDo == null) whatToDo = ask("What to do? (filter/retainingpath)");
  if (whatToDo == "retainingpath") {
    await vm.printRetainingPaths(isolateId, classToFind);
  } else {
    await vm.printAllocationProfile(isolateId, filter: classToFind);
    String fieldToFilter = ask("Filter on what field");
    Set<String> fieldValues = {};
    while (true) {
      String fieldValue = ask("Look for value in field (empty to stop)");
      if (fieldValue == "") break;
      fieldValues.add(fieldValue);
    }

    await vm.filterAndPrintInstances(
        isolateId, classToFind, fieldToFilter, fieldValues);
  }

  await vm.disconnect();
  print("Disconnect done!");
}

String ask(String question) {
  stdout.write("$question: ");
  return stdin.readLineSync();
}

class VMServiceHeapHelperPrinter extends vmService.VMServiceHelper {
  Future<void> printAllocationProfile(String isolateId, {String filter}) async {
    await waitUntilIsolateIsRunnable(isolateId);
    vmService.AllocationProfile allocationProfile =
        await serviceClient.getAllocationProfile(isolateId);
    for (vmService.ClassHeapStats member in allocationProfile.members) {
      if (filter != null) {
        if (member.classRef.name != filter) continue;
      } else {
        if (member.classRef.name == "") continue;
        if (member.instancesCurrent == 0) continue;
      }
      vmService.Class c =
          await serviceClient.getObject(isolateId, member.classRef.id);
      if (c.location?.script?.uri == null) continue;
      print("${member.classRef.name}: ${member.instancesCurrent}");
    }
  }

  Future<void> filterAndPrintInstances(String isolateId, String filter,
      String fieldName, Set<String> fieldValues) async {
    await waitUntilIsolateIsRunnable(isolateId);
    vmService.AllocationProfile allocationProfile =
        await serviceClient.getAllocationProfile(isolateId);
    for (vmService.ClassHeapStats member in allocationProfile.members) {
      if (member.classRef.name != filter) continue;
      vmService.Class c =
          await serviceClient.getObject(isolateId, member.classRef.id);
      if (c.location?.script?.uri == null) continue;
      print("${member.classRef.name}: ${member.instancesCurrent}");
      print(c.location.script.uri);

      vmService.InstanceSet instances = await serviceClient.getInstances(
          isolateId, member.classRef.id, 10000);
      int instanceNum = 0;
      for (vmService.ObjRef instance in instances.instances) {
        instanceNum++;
        vmService.Obj receivedObject =
            await serviceClient.getObject(isolateId, instance.id);
        if (receivedObject is! vmService.Instance) continue;
        vmService.Instance object = receivedObject;
        for (vmService.BoundField field in object.fields) {
          if (field.decl.name == fieldName) {
            if (field.value is vmService.Sentinel) continue;
            vmService.Obj receivedValue =
                await serviceClient.getObject(isolateId, field.value.id);
            if (receivedValue is! vmService.Instance) continue;
            String value = (receivedValue as vmService.Instance).valueAsString;
            if (!fieldValues.contains(value)) continue;
            print("${instanceNum}: ${field.decl.name}: "
                "${value} --- ${instance.id}");
          }
        }
      }
    }
    print("Done!");
  }

  Future<void> printRetainingPaths(String isolateId, String filter) async {
    await waitUntilIsolateIsRunnable(isolateId);
    vmService.AllocationProfile allocationProfile =
        await serviceClient.getAllocationProfile(isolateId);
    for (vmService.ClassHeapStats member in allocationProfile.members) {
      if (member.classRef.name != filter) continue;
      vmService.Class c =
          await serviceClient.getObject(isolateId, member.classRef.id);
      print("Found ${c.name} (location: ${c.location})");
      print("${member.classRef.name}: "
          "(instancesCurrent: ${member.instancesCurrent})");
      print("");

      vmService.InstanceSet instances = await serviceClient.getInstances(
          isolateId, member.classRef.id, 10000);
      print(" => Got ${instances.instances.length} instances");
      print("");

      for (vmService.ObjRef instance in instances.instances) {
        vmService.Obj receivedObject =
            await serviceClient.getObject(isolateId, instance.id);
        print("Instance: $receivedObject");
        vmService.RetainingPath retainingPath =
            await serviceClient.getRetainingPath(isolateId, instance.id, 1000);
        print("Retaining path: (length ${retainingPath.length}");
        for (int i = 0; i < retainingPath.elements.length; i++) {
          print("  [$i] = ${retainingPath.elements[i]}");
        }

        print("");
      }
    }
    print("Done!");
  }
}
