// Copyright (c) 2024, 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:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';

import 'package:devtools_shared/devtools_shared.dart' show DtdInfo;
import 'package:path/path.dart' as path;

import 'utils.dart';

String getDTDSnapshotDir() {
  // This logic is originally from pkg/dartdev/lib/src/sdk.dart
  //
  // Find SDK path.
  (String, bool)? trySDKPath(String executablePath) {
    // The common case, and how cli_util.dart computes the Dart SDK directory,
    // [path.dirname] called twice on Platform.executable. We confirm by
    // asserting that the directory `./bin/snapshots/` exists in this directory:
    var sdkPath = path.absolute(path.dirname(path.dirname(executablePath)));
    var snapshotsDir = path.join(sdkPath, 'bin', 'snapshots');
    var runFromBuildRoot = false;
    final type = FileSystemEntity.typeSync(snapshotsDir);
    if (type != FileSystemEntityType.directory &&
        type != FileSystemEntityType.link) {
      // This is the less common case where the user is in
      // the checked out Dart SDK, and is executing `dart` via:
      // ./out/ReleaseX64/dart ... or in google3.
      sdkPath = path.absolute(path.dirname(executablePath));
      snapshotsDir = sdkPath;
      runFromBuildRoot = true;
    }

    // Try to locate the DDS snapshot to determine if we're able to find
    // the SDK snapshots with this SDK path. This is meant to handle
    // non-standard SDK layouts that can involve symlinks (e.g., Brew
    // installations, google3 tests, etc).
    if (!File(
      path.join(snapshotsDir, 'dart_tooling_daemon_aot.dart.snapshot'),
    ).existsSync()) {
      // We do not have an AOT snpashot and hence look for the JIT snapshot.
      if (!File(
        path.join(snapshotsDir, 'dart_tooling_daemon.dart.snapshot'),
      ).existsSync()) {
        return null;
      }
    }
    return (sdkPath, runFromBuildRoot);
  }

  final (sdkPath, runFromBuildRoot) = trySDKPath(Platform.resolvedExecutable) ??
      trySDKPath(Platform.executable)!;

  final String snapshotDir;
  if (runFromBuildRoot) {
    snapshotDir = sdkPath;
  } else {
    snapshotDir = path.absolute(sdkPath, 'bin', 'snapshots');
  }

  return snapshotDir;
}

Future<DtdInfo?> startDtd({
  required bool machineMode,
  required bool printDtdUri,
}) async {
  final snapshotDir = getDTDSnapshotDir();
  final dtdAotSnapshot = path.absolute(
    snapshotDir,
    'dart_tooling_daemon_aot.dart.snapshot',
  );
  final completer = Completer<DtdInfo?>();
  void completeForError([_]) => completer.complete(null);

  final exitPort = ReceivePort()..listen(completeForError);
  final errorPort = ReceivePort()..listen(completeForError);
  final receivePort = ReceivePort()
    ..listen((message) {
      try {
        // [message] is a JSON encoded String from package:dtd_impl.
        final json = jsonDecode(message) as Map<String, Object?>;
        if (json
            case {
              'tooling_daemon_details': {
                'uri': String uri,
                'trusted_client_secret': String secret,
              }
            }) {
          if (printDtdUri || machineMode) {
            DevToolsUtils.printOutput(
              'Serving the Dart Tooling Daemon at $uri',
              {
                'event': 'server.dtdStarted',
                'params': {'uri': uri},
              },
              machineMode: machineMode,
            );
          }
          completer.complete(DtdInfo(Uri.parse(uri), secret: secret));
        }
      } catch (_) {
        completeForError();
      }
    });

  try {
    // Try to spawn an isolate using the AOT snapshot of the tooling daemon.
    await Isolate.spawnUri(
      Uri.file(dtdAotSnapshot),
      ['--machine'],
      receivePort.sendPort,
      onExit: exitPort.sendPort,
      onError: errorPort.sendPort,
    );
  } catch (_) {
    // Spawning an isolate using the AOT snapshot of the tooling daemon failed,
    // try again using the JIT snapshot of the tooling daemon.
    final dtdSnapshot = path.absolute(
      snapshotDir,
      'dart_tooling_daemon.dart.snapshot',
    );
    try {
      await Isolate.spawnUri(
        Uri.file(dtdSnapshot),
        ['--machine'],
        receivePort.sendPort,
        onExit: exitPort.sendPort,
        onError: errorPort.sendPort,
      );
    } catch (_) {
      completeForError();
    }
  }

  final result = await completer.future.timeout(
    const Duration(seconds: 5),
    onTimeout: () => null,
  );
  receivePort.close();
  errorPort.close();
  exitPort.close();
  return result;
}
