// Copyright (c) 2016, 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 'dart:isolate';

import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:async/async.dart';
import 'package:path/path.dart' as p;
import 'package:stream_channel/isolate_channel.dart';
import 'package:stream_channel/stream_channel.dart';
// ignore: deprecated_member_use
import 'package:test_api/backend.dart' show RemoteException;
import 'package:test_api/src/backend/suite.dart'; // ignore: implementation_imports

import '../util/dart.dart' as dart;
import '../util/package_config.dart';
import 'package_version.dart';

/// Spawns a hybrid isolate from [url] with the given [message], and returns a
/// [StreamChannel] that communicates with it.
///
/// This connects the main isolate to the hybrid isolate, whereas
/// `lib/src/frontend/spawn_hybrid.dart` connects the test isolate to the main
/// isolate.
///
/// If [uri] is relative, it will be interpreted relative to the `file:` URL
/// for [suite]. If it's root-relative (that is, if it begins with `/`) it will
/// be interpreted relative to the root of the package (the directory that
/// contains `pubspec.yaml`, *not* the `test/` directory). If it's a `package:`
/// URL, it will be resolved using the current package's dependency
/// constellation.
StreamChannel spawnHybridUri(String url, Object? message, Suite suite) {
  url = _normalizeUrl(url, suite);
  return StreamChannelCompleter.fromFuture(() async {
    var port = ReceivePort();
    var onExitPort = ReceivePort();
    try {
      var code = '''
        ${await _languageVersionCommentFor(url)}

        import "package:test_core/src/runner/hybrid_listener.dart";

        import "${url.replaceAll(r'$', '%24')}" as lib;

        void main(_, List data) => listen(() => lib.hybridMain, data);
      ''';

      var isolate = await dart.runInIsolate(code, [port.sendPort, message],
          onExit: onExitPort.sendPort);

      // Ensure that we close [port] and [channel] when the isolate exits.
      var disconnector = Disconnector();
      onExitPort.listen((_) {
        disconnector.disconnect();
        onExitPort.close();
      });

      return IsolateChannel.connectReceive(port)
          .transform(disconnector)
          .transformSink(StreamSinkTransformer.fromHandlers(handleDone: (sink) {
        // If the user closes the stream channel, kill the isolate.
        isolate.kill();
        onExitPort.close();
        sink.close();
      }));
    } catch (error, stackTrace) {
      port.close();
      onExitPort.close();

      // Make sure any errors in spawning the isolate are forwarded to the test.
      return StreamChannel(
          Stream.fromFuture(Future.value({
            'type': 'error',
            'error': RemoteException.serialize(error, stackTrace)
          })),
          NullStreamSink());
    }
  }());
}

/// Normalizes [url] to an absolute url, or returns it as is if it has a
/// scheme.
///
/// Follows the rules for relative/absolute paths outlined in [spawnHybridUri].
String _normalizeUrl(String url, Suite suite) {
  final parsedUri = Uri.parse(url);

  if (parsedUri.scheme.isEmpty) {
    var isRootRelative = parsedUri.path.startsWith('/');

    if (isRootRelative) {
      // We assume that the current path is the package root. `pub run`
      // enforces this currently, but at some point it would probably be good
      // to pass in an explicit root.
      return p.url
          .join(p.toUri(p.current).toString(), parsedUri.path.substring(1));
    } else {
      var suitePath = suite.path!;
      return p.url.join(
          p.url.dirname(p.toUri(p.absolute(suitePath)).toString()),
          parsedUri.toString());
    }
  } else {
    return url;
  }
}

/// Computes the a language version comment for the library at [uri].
///
/// If there is a language version comment in the file, that is returned.
///
/// If the URI has a `data` scheme, a comment representing the language version of
/// the current package is returned.
///
/// Otherwise a comment representing the default version from the
/// [currentPackageConfig] is returned.
///
/// If no default language version is known (the URI scheme is not recognized
/// for instance), then an empty string is returned.
Future<String> _languageVersionCommentFor(String url) async {
  var parsedUri = Uri.parse(url);

  // Returns the explicit language version comment if one exists.
  var result = parseString(
      content: await _readUri(parsedUri),
      path: parsedUri.scheme == 'data' ? null : p.fromUri(parsedUri),
      throwIfDiagnostics: false);
  var languageVersionComment = result.unit.languageVersionToken?.value();
  if (languageVersionComment != null) return languageVersionComment.toString();

  // Returns the default language version for the package if one exists.
  if (parsedUri.scheme.isEmpty || parsedUri.scheme == 'file') {
    var packageConfig = await currentPackageConfig;
    var package = packageConfig.packageOf(parsedUri);
    var version = package?.languageVersion;
    if (version != null) return '// @dart=$version';
  }

  // Returns the root package language version for `data` URIs. These are
  // assumed to be from `spawnHybridCode` calls.
  if (parsedUri.scheme == 'data') {
    return await rootPackageLanguageVersionComment;
  }

  // Fall back on no language comment.
  return '';
}

Future<String> _readUri(Uri uri) async {
  switch (uri.scheme) {
    case '':
    case 'file':
      return File.fromUri(uri).readAsString();
    case 'data':
      return uri.data!.contentAsString();
    default:
      throw ArgumentError.value(uri, 'uri',
          'Only data and file uris (as well as relative paths) are supported');
  }
}
