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

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!) as vmService.Class;
      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!) as vmService.Class;
      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.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!) as vmService.Class;
      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!");
  }
}
