// Copyright (c) 2021, 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' hide Link;
import 'dart:isolate';

import 'package:compiler/src/compiler.dart';
import 'package:expect/async_helper.dart';
import 'package:expect/expect.dart';
import 'package:kernel/ast.dart' as ir;

import '../equivalence/id_equivalence_helper.dart';
import '../deferred_loading/deferred_loading_test_helper.dart';

///  Add in options to pass to the compiler like
/// `Flags.disableTypeInference` or `Flags.disableInlining`
const List<String> compilerOptions = const [];

const List<String> tests = [
  'diamond',
  'diamond_and',
  'diamond_fuse',
  'diamond_or',
  'fuse_with_and',
  'fuse_with_or',
  'two_step',
  'two_branch',
  'just_fuse',
];

Map<String, List<String>> createPerTestOptions() {
  Map<String, List<String>> perTestOptions = {};
  for (var test in tests) {
    Uri constraints = Platform.script.resolve('data/$test/constraints.json');
    perTestOptions['$test'] = ['--read-program-split=$constraints'];
  }
  return perTestOptions;
}

/// Returns a list of the deferred imports in a component where each import
/// becomes a string of 'uri#prefix'.
List<String> getDeferredImports(ir.Component component) {
  List<String> imports = [];
  for (var library in component.libraries) {
    for (var import in library.dependencies) {
      if (import.isDeferred) {
        imports.add('${library.importUri}#${import.name}');
      }
    }
  }
  imports.sort();
  return imports;
}

/// A helper function which performs the following steps:
/// 1) Get deferred imports from a given [component]
/// 2) Spawns the supplied [constraintsUri] in its own isolate
/// 3) Passes deferred imports via a port to the spawned isolate
/// 4) Listens for a json string from the spawned isolated and returns the
///    results as a [Future<String>].
Future<String> constraintsToJson(
  ir.Component component,
  Uri constraintsUri,
) async {
  var imports = getDeferredImports(component);
  SendPort? sendPort;
  var receivePort = ReceivePort();
  var isolate = await Isolate.spawnUri(
    constraintsUri,
    [],
    receivePort.sendPort,
    paused: true,
  );
  isolate.addOnExitListener(receivePort.sendPort);
  isolate.resume(isolate.pauseCapability!);
  String? json;
  await for (var msg in receivePort) {
    if (msg == null) {
      receivePort.close();
    } else if (sendPort == null) {
      sendPort = msg;
      sendPort!.send(imports);
    } else if (json == null) {
      json = msg;
    } else {
      throw 'Unexpected message $msg';
    }
  }
  return json!;
}

Uri getFileInTestFolder(String test, String file) =>
    Platform.script.resolve('data/$test/$file');

Future<String> compileConstraintsToJson(String test, Compiler compiler) async {
  var constraints = getFileInTestFolder(test, 'constraints.dart');
  var component = compiler.componentForTesting;
  return constraintsToJson(component, constraints);
}

File getConstraintsJsonFile(String test) {
  var constraintsJsonUri = getFileInTestFolder(test, 'constraints.json');
  return File(constraintsJsonUri.toFilePath());
}

/// Verifies the programmatic API produces the expected JSON.
Future<void> verifyCompiler(String test, Compiler compiler) async {
  var json = await compileConstraintsToJson(test, compiler);
  Expect.equals(getConstraintsJsonFile(test).readAsStringSync(), json);
}

/// Generates constraint JSON.
Future<void> generateJSON(String test, Compiler compiler) async {
  var json = await compileConstraintsToJson(test, compiler);
  getConstraintsJsonFile(test).writeAsStringSync(json);
}

/// Compute the [OutputUnit]s for all source files involved in the test, and
/// ensure that the compiler is correctly calculating what is used and what is
/// not. We expect all test entry points to be in the `data` directory and any
/// or all supporting libraries to be in the `libs` folder, starting with the
/// same name as the original file in `data`.
main(List<String> args) {
  bool generateGoldens = args.contains('-g');
  asyncTest(() async {
    Directory dataDir = Directory.fromUri(Platform.script.resolve('data'));
    await checkTests(
      dataDir,
      const OutputUnitDataComputer(),
      options: compilerOptions,
      perTestOptions: createPerTestOptions(),
      args: args,
      setUpFunction: () {
        importPrefixes.clear();
      },
      testedConfigs: allSpecConfigs,
      verifyCompiler: generateGoldens ? generateJSON : verifyCompiler,
    );
  });
}
