// 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:convert";
import "dart:io";

import "package:vm_service/vm_service.dart" as vmService;
import "package:vm_service/vm_service_io.dart" as vmService;

export "package:vm_service/vm_service.dart";
export "package:vm_service/vm_service_io.dart";

class VMServiceHelper {
  late vmService.VmService _serviceClient;
  vmService.VmService get serviceClient => _serviceClient;

  VMServiceHelper();

  Future connect(Uri observatoryUri) async {
    String path = observatoryUri.path;
    if (!path.endsWith("/")) path += "/";
    String wsUriString = 'ws://${observatoryUri.authority}${path}ws';
    _serviceClient = await vmService.vmServiceConnectUri(wsUriString,
        log: const StdOutLog());
  }

  Future disconnect() async {
    await _serviceClient.dispose();
  }

  Future<void> resumeAllIsolates() async {
    vmService.VM vm = await serviceClient.getVM();
    for (vmService.IsolateRef isolate in vm.isolates!) {
      try {
        await serviceClient.resume(isolate.id!);
      } catch (e) {
        // It might exit at some point so we can't expect to get a good result.
      }
    }
  }

  Future<void> waitUntilSomeIsolatePausedAtExit() async {
    while (true) {
      vmService.VM vm = await serviceClient.getVM();
      if (vm.isolates!.isNotEmpty) {
        for (vmService.IsolateRef isolate in vm.isolates!) {
          String isolateId = isolate.id!;
          if (await isPausedAtExit(isolateId) == true) {
            return;
          }
        }
      }
      await Future.delayed(const Duration(milliseconds: 10));
    }
  }

  Future<bool> waitUntilPaused(String isolateId) async {
    int nulls = 0;
    int tries = 0;
    while (true) {
      tries++;
      bool? result = await isPaused(isolateId);
      if (result == null) {
        nulls++;
        if (nulls > 5) {
          // We've now asked for the isolate 5 times and in all cases gotten
          // `Sentinel`. Most likely things aren't working for whatever reason.
          return false;
        }
      } else if (result) {
        return true;
      } else {
        if (tries > 50) {
          // Waited 5+ seconds --- check if some isolate is paused at start
          // and resume if it is. This is for instance the case with macros.
          await _resumeAllPausedAtStartIsolates();
          tries = 0;
        }
        await Future.delayed(const Duration(milliseconds: 100));
      }
    }
  }

  Future<void> _resumeAllPausedAtStartIsolates() async {
    vmService.VM vm = await serviceClient.getVM();
    for (vmService.IsolateRef isolateRef in vm.isolates!) {
      try {
        String? id = isolateRef.id;
        if (id == null) continue;
        vmService.Isolate isolate = await _serviceClient.getIsolate(id);
        if (isolate.pauseEvent?.kind == "PauseStart") {
          print("Found isolate paused at start - resuming it.");
          await serviceClient.resume(id);
        }
      } catch (e) {
        // It might exit at some point so we can't expect to get a good result.
      }
    }
  }

  Future<bool?> isPaused(String isolateId) async {
    vmService.Isolate isolate = await _serviceClient.getIsolate(isolateId);
    String? kind = isolate.pauseEvent!.kind;
    if (kind != "Resume" && kind != "None") return true;
    return false;
  }

  Future<bool> isPausedAtStart(String isolateId) async {
    dynamic tmp = await _serviceClient.getIsolate(isolateId);
    if (tmp is vmService.Isolate) {
      vmService.Isolate isolate = tmp;
      return isolate.pauseEvent!.kind == "PauseStart";
    }
    return false;
  }

  Future<bool> isPausedAtExit(String isolateId) async {
    vmService.Isolate isolate = await _serviceClient.getIsolate(isolateId);
    return isolate.pauseEvent!.kind == "PauseExit";
  }

  Future<vmService.AllocationProfile> forceGC(String isolateId) async {
    await waitUntilIsolateIsRunnable(isolateId);
    int expectGcAfter = new DateTime.now().millisecondsSinceEpoch;
    while (true) {
      vmService.AllocationProfile allocationProfile;
      try {
        allocationProfile =
            await _serviceClient.getAllocationProfile(isolateId, gc: true);
      } catch (e) {
        print(e.runtimeType);
        rethrow;
      }
      if (allocationProfile.dateLastServiceGC != null &&
          allocationProfile.dateLastServiceGC! >= expectGcAfter) {
        return allocationProfile;
      }
    }
  }

  Future<bool?> isIsolateRunnable(String isolateId) async {
    dynamic tmp = await _serviceClient.getIsolate(isolateId);
    if (tmp is vmService.Isolate) {
      vmService.Isolate isolate = tmp;
      return isolate.runnable;
    }
    return null;
  }

  Future<void> waitUntilIsolateIsRunnable(String isolateId) async {
    int nulls = 0;
    while (true) {
      bool? result = await isIsolateRunnable(isolateId);
      if (result == null) {
        nulls++;
        if (nulls > 5) {
          // We've now asked for the isolate 5 times and in all cases gotten
          // `Sentinel`. Most likely things aren't working for whatever reason.
          return;
        }
      } else if (result) {
        return;
      } else {
        await Future.delayed(const Duration(milliseconds: 100));
      }
    }
  }

  Future<String> getIsolateId() async {
    vmService.VM vm = await _serviceClient.getVM();
    if (vm.isolates!.length != 1) {
      throw "Expected 1 isolate, got ${vm.isolates!.length}";
    }
    vmService.IsolateRef isolateRef = vm.isolates!.single;
    return isolateRef.id!;
  }
}

class StdOutLog implements vmService.Log {
  const StdOutLog();

  @override
  void severe(String message) {
    print("> SEVERE: $message");
  }

  @override
  void warning(String message) {
    print("> WARNING: $message");
  }
}

abstract class LaunchingVMServiceHelper extends VMServiceHelper {
  late Process _process;
  Process get process => _process;

  bool _started = false;

  Future<void> start(
    List<String> scriptAndArgs, {
    void Function(String line)? stdoutReceiver,
    void Function(String line)? stderrReceiver,
    bool pauseIsolateOnStart = true,
  }) async {
    if (_started) throw "Already started";
    _started = true;
    _process = await Process.start(Platform.resolvedExecutable, [
      if (pauseIsolateOnStart) "--pause_isolates_on_start",
      "--enable-vm-service=0",
      ...scriptAndArgs
    ]);
    _process.stdout
        .transform(utf8.decoder)
        .transform(new LineSplitter())
        .listen((line) {
      const kDartVMServiceListening = 'The Dart VM service is listening on ';
      if (line.startsWith(kDartVMServiceListening)) {
        Uri observatoryUri =
            Uri.parse(line.substring(kDartVMServiceListening.length));
        _setupAndRun(observatoryUri).catchError((e, st) {
          // Manually kill the process or it will leak,
          // see http://dartbug.com/42918
          killProcess();
          // This seems to rethrow.
          throw e;
        });
      }
      if (stdoutReceiver != null) {
        stdoutReceiver(line);
      } else {
        stdout.writeln("> $line");
      }
    });
    _process.stderr
        .transform(utf8.decoder)
        .transform(new LineSplitter())
        .listen((line) {
      if (stderrReceiver != null) {
        stderrReceiver(line);
      } else {
        stderr.writeln("> $line");
      }
    });
    // ignore: unawaited_futures
    _process.exitCode.then((value) {
      processExited(value);
    });
  }

  Future<void> startWithoutRunning(Uri observatoryUri) async {
    if (_started) throw "Already started";
    _started = true;
    await _setupAndRun(observatoryUri);
  }

  void processExited(int exitCode) {}

  void killProcess() {
    _process.kill();
  }

  Future _setupAndRun(Uri observatoryUri) async {
    await connect(observatoryUri);
    await run();
  }

  Future<void> run();
}
