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

// Warning: This file has to start up fast so we can't import lots of stuff.
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';

import 'test/utils/io_utils.dart';

Future<void> main(List<String> args) async {
  Stopwatch stopwatch = new Stopwatch()..start();
  // Expect something like /full/path/to/sdk/pkg/some_dir/whatever/else
  if (args.length != 1) throw "Need exactly one argument.";

  final List<String> changedFiles = getChangedFiles();
  String callerPath = args[0].replaceAll("\\", "/");
  if (!_shouldRun(changedFiles, callerPath)) {
    return;
  }

  List<Work> workItems = [];

  // This run is now the only run that will actually run any smoke tests.
  // First collect all relevant smoke tests.
  // Note that this is *not* perfect, e.g. it might think there's no reason for
  // a test because the tested hasn't changed even though the actual test has.
  // E.g. if you only update the spelling dictionary no spell test will be run
  // because the files being spell-tested hasn't changed.
  workItems.addIfNotNull(_createExplicitCreationTestWork(changedFiles));
  workItems.addIfNotNull(_createMessagesTestWork(changedFiles));
  workItems.addIfNotNull(_createSpellingTestNotSourceWork(changedFiles));
  workItems.addIfNotNull(_createSpellingTestSourceWork(changedFiles));
  workItems.addIfNotNull(_createLintWork(changedFiles));
  workItems.addIfNotNull(_createDepsTestWork(changedFiles));
  bool shouldRunGenerateFilesTest = _shouldRunGenerateFilesTest(changedFiles);

  // Then run them if we have any.
  if (workItems.isEmpty && !shouldRunGenerateFilesTest) {
    print("Nothing to do.");
    return;
  }

  List<Future> futures = [];
  if (shouldRunGenerateFilesTest) {
    print("Running generated_files_up_to_date_git_test in different process.");
    futures.add(_run(
        "pkg/front_end/test/generated_files_up_to_date_git_test.dart",
        const []));
  }

  if (workItems.isNotEmpty) {
    print("Will now run ${workItems.length} tests.");
    futures.add(_executePendingWorkItems(workItems));
  }

  await Future.wait(futures);
  print("All done in ${stopwatch.elapsed}");
}

/// Map from a dir name in "pkg" to the inner-dir we want to include in the
/// explicit creation test.
const Map<String, String> _explicitCreationDirs = {
  "frontend_server": "",
  "front_end": "lib/",
  "_fe_analyzer_shared": "lib/",
};

/// This is currently a representative list of the dependencies, but do update
/// if it turns out to be needed.
const Set<String> _generatedFilesUpToDateFiles = {
  "pkg/_fe_analyzer_shared/lib/src/experiments/flags.dart",
  "pkg/_fe_analyzer_shared/lib/src/messages/codes_generated.dart",
  "pkg/_fe_analyzer_shared/lib/src/parser/listener.dart",
  "pkg/_fe_analyzer_shared/lib/src/parser/parser_impl.dart",
  "pkg/front_end/lib/src/api_prototype/experimental_flags_generated.dart",
  "pkg/front_end/lib/src/fasta/codes/fasta_codes_cfe_generated.dart",
  "pkg/front_end/lib/src/fasta/util/parser_ast_helper.dart",
  "pkg/front_end/messages.yaml",
  "pkg/front_end/test/generated_files_up_to_date_git_test.dart",
  "pkg/front_end/test/parser_test_listener_creator.dart",
  "pkg/front_end/test/parser_test_listener.dart",
  "pkg/front_end/test/parser_test_parser_creator.dart",
  "pkg/front_end/test/parser_test_parser.dart",
  "pkg/front_end/tool/_fasta/generate_messages.dart",
  "pkg/front_end/tool/_fasta/parser_ast_helper_creator.dart",
  "pkg/front_end/tool/generate_ast_coverage.dart",
  "pkg/front_end/tool/generate_ast_equivalence.dart",
  "pkg/front_end/tool/visitor_generator.dart",
  "pkg/kernel/lib/ast.dart",
  "pkg/kernel/lib/default_language_version.dart",
  "pkg/kernel/lib/src/ast/patterns.dart",
  "pkg/kernel/lib/src/coverage.dart",
  "pkg/kernel/lib/src/equivalence.dart",
  "sdk/lib/libraries.json",
  "tools/experimental_features.yaml",
};

/// Map from a dir name in "pkg" to the inner-dir we want to include in the
/// lint test.
const Map<String, String> _lintDirs = {
  "frontend_server": "",
  "front_end": "lib/",
  "kernel": "lib/",
  "_fe_analyzer_shared": "lib/",
};

/// Map from a dir name in "pkg" to the inner-dirs we want to include in the
/// spelling (source) test.
const Map<String, List<String>> _spellDirs = {
  "frontend_server": ["lib/", "bin/"],
  "kernel": ["lib/", "bin/"],
  "front_end": ["lib/"],
  "_fe_analyzer_shared": ["lib/"],
};

/// Set of dirs in "pkg" we care about.
const Set<String> _usDirs = {
  "kernel",
  "frontend_server",
  "front_end",
  "_fe_analyzer_shared",
};

final Uri _repoDir = computeRepoDirUri();

String get _dartVm => Platform.executable;

DepsTestWork? _createDepsTestWork(List<String> changedFiles) {
  bool foundFiles = false;
  for (String path in changedFiles) {
    if (!path.endsWith(".dart")) continue;
    if (path.startsWith("pkg/front_end/lib/")) {
      foundFiles = true;
      break;
    }
  }

  if (!foundFiles) return null;

  return new DepsTestWork();
}

ExplicitCreationWork? _createExplicitCreationTestWork(
    List<String> changedFiles) {
  Set<Uri> includedDirs = {};
  for (MapEntry<String, String> entry in _explicitCreationDirs.entries) {
    includedDirs.add(_repoDir.resolve("pkg/${entry.key}/${entry.value}"));
  }

  Set<Uri> files = {};
  for (String path in changedFiles) {
    if (!path.endsWith(".dart")) continue;
    bool found = false;
    for (MapEntry<String, String> usDirEntry in _explicitCreationDirs.entries) {
      if (path.startsWith("pkg/${usDirEntry.key}/${usDirEntry.value}")) {
        found = true;
        break;
      }
    }
    if (!found) continue;
    files.add(_repoDir.resolve(path));
  }

  if (files.isEmpty) return null;

  return new ExplicitCreationWork(
      includedFiles: files,
      includedDirectoryUris: includedDirs,
      repoDir: _repoDir);
}

LintWork? _createLintWork(List<String> changedFiles) {
  List<String> filters = [];
  pathLoop:
  for (String path in changedFiles) {
    if (!path.endsWith(".dart")) continue;
    for (MapEntry<String, String> entry in _lintDirs.entries) {
      if (path.startsWith("pkg/${entry.key}/${entry.value}")) {
        String filter = path.substring("pkg/".length, path.length - 5);
        filters.add("lint/$filter/...");
        continue pathLoop;
      }
    }
  }

  if (filters.isEmpty) return null;

  return new LintWork(filters: filters, repoDir: _repoDir);
}

MessagesWork? _createMessagesTestWork(List<String> changedFiles) {
  // TODO(jensj): Could we detect what ones are changed/added and only test
  // those?
  for (String file in changedFiles) {
    if (file == "pkg/front_end/messages.yaml") {
      return new MessagesWork(repoDir: _repoDir);
    }
  }

  // messages.yaml not changed.
  return null;
}

SpellNotSourceWork? _createSpellingTestNotSourceWork(
    List<String> changedFiles) {
  // TODO(jensj): Not here, but I'll add the note here.
  // package:testing takes *a long time* listing files because it does
  // ```
  // if (suite.exclude.any((RegExp r) => path.contains(r))) continue;
  // if (suite.pattern.any((RegExp r) => path.contains(r))) {}
  // ```
  // for each file it finds. Maybe it should do something more efficient,
  // and maybe it should even take given filters into account at this point?
  //
  // Also it lists all files in the specified "path", so for instance for the
  // src spell one we have to list all files in "pkg/", then filter it down to
  // stuff in one of the dirs we care about.
  List<String> filters = [];
  for (String path in changedFiles) {
    if (!path.endsWith(".dart")) continue;
    if (path.startsWith("pkg/front_end/") &&
        !path.startsWith("pkg/front_end/lib/")) {
      // Remove front of path and ".dart".
      String filter = path.substring("pkg/front_end/".length, path.length - 5);
      filters.add("spelling_test_not_src/$filter");
    }
  }

  if (filters.isEmpty) return null;

  return new SpellNotSourceWork(filters: filters, repoDir: _repoDir);
}

SpellSourceWork? _createSpellingTestSourceWork(List<String> changedFiles) {
  List<String> filters = [];
  pathLoop:
  for (String path in changedFiles) {
    if (!path.endsWith(".dart")) continue;
    for (MapEntry<String, List<String>> entry in _spellDirs.entries) {
      for (String subPath in entry.value) {
        if (path.startsWith("pkg/${entry.key}/$subPath")) {
          String filter = path.substring("pkg/".length, path.length - 5);
          filters.add("spelling_test_src/$filter");
          continue pathLoop;
        }
      }
    }
  }

  if (filters.isEmpty) return null;

  return new SpellSourceWork(filters: filters, repoDir: _repoDir);
}

Future<void> _executePendingWorkItems(List<Work> workItems) async {
  int currentlyRunning = 0;
  SpawnHelper spawnHelper = new SpawnHelper();
  print("Waiting for spawn to start up.");
  Stopwatch stopwatch = new Stopwatch()..start();
  await spawnHelper
      .spawn(_repoDir.resolve("pkg/front_end/presubmit_helper_spawn.dart"),
          (dynamic ok) {
    if (ok is! bool) {
      exitCode = 1;
      print("Error got message of type ${ok.runtimeType}");
      return;
    }
    currentlyRunning--;
    if (!ok) {
      exitCode = 1;
    }
  });
  print("Isolate started in ${stopwatch.elapsed}");

  for (Work workItem in workItems) {
    print("Executing ${workItem.name}.");
    currentlyRunning++;
    spawnHelper.send(json.encode(workItem.toJson()));
  }

  while (currentlyRunning > 0) {
    await Future.delayed(const Duration(milliseconds: 42));
  }
  spawnHelper.close();
}

/// Queries git about changes against upstream, or origin/main if no upstream is
/// set. This is similar (but different), I believe, to what
/// `git cl presubmit` does.
List<String> getChangedFiles() {
  ProcessResult result = Process.runSync(
      "git",
      [
        "-c",
        "core.quotePath=false",
        "diff",
        "--name-status",
        "--no-renames",
        "@{u}...HEAD"
      ],
      runInShell: true);
  if (result.exitCode != 0) {
    result = Process.runSync(
        "git",
        [
          "-c",
          "core.quotePath=false",
          "diff",
          "--name-status",
          "--no-renames",
          "origin/main...HEAD"
        ],
        runInShell: true);
  }
  if (result.exitCode != 0) {
    throw "Failure";
  }

  List<String> paths = [];
  for (String line in result.stdout.toString().split("\n")) {
    List<String> split = line.split("\t");
    if (split.length != 2) continue;
    if (split[0] == 'D') continue; // Don't check deleted files.
    String path = split[1].trim().replaceAll("\\", "/");
    paths.add(path);
  }
  return paths;
}

/// If [inner] is a dir or file inside [outer] this returns the index into
/// `inner.pathSegments` corresponding to the folder- or filename directly
/// inside [outer].
/// If [inner] is not inside [outer] it returns null.
int? _getPathSegmentIndexIfSubEntry(Uri outer, Uri inner) {
  List<String> outerPathSegments = outer.pathSegments;
  List<String> innerPathSegments = inner.pathSegments;
  if (innerPathSegments.length < outerPathSegments.length) return null;
  int end = outerPathSegments.length;
  if (outerPathSegments.last == "") end--;
  for (int i = 0; i < end; i++) {
    if (Platform.isWindows) {
      if (outerPathSegments[i].toLowerCase() !=
          innerPathSegments[i].toLowerCase()) {
        return null;
      }
    } else {
      if (outerPathSegments[i] != innerPathSegments[i]) {
        return null;
      }
    }
  }
  return end;
}

Future<void> _run(
  String script,
  List<String> scriptArguments,
) async {
  List<String> arguments = [];
  arguments.add("$script");
  arguments.addAll(scriptArguments);

  Stopwatch stopwatch = new Stopwatch()..start();
  ProcessResult result = await Process.run(_dartVm, arguments,
      workingDirectory: _repoDir.toFilePath());
  String runWhat = "${_dartVm} ${arguments.join(' ')}";
  if (result.exitCode != 0) {
    exitCode = result.exitCode;
    print("-----");
    print("Running: $runWhat: "
        "Failed with exit code ${result.exitCode} "
        "in ${stopwatch.elapsedMilliseconds} ms.");
    String stdout = result.stdout.toString();
    stdout = stdout.trim();
    if (stdout.isNotEmpty) {
      print("--- stdout start ---");
      print(stdout);
      print("--- stdout end ---");
    }

    String stderr = result.stderr.toString().trim();
    if (stderr.isNotEmpty) {
      print("--- stderr start ---");
      print(stderr);
      print("--- stderr end ---");
    }
  } else {
    print("Running: $runWhat: Done in ${stopwatch.elapsedMilliseconds} ms.");
  }
}

// This script is potentially called from several places (once from each),
// but we only want to actually run it once. To that end we - from the changed
// files figure out which would call this script, and only if the caller is
// the top one (just alphabetically sorted) we actually run.
bool _shouldRun(final List<String> changedFiles, final String callerPath) {
  Uri pkgDir = _repoDir.resolve("pkg/");
  Uri callerUri = Uri.base.resolveUri(Uri.file(callerPath));
  int? endPathIndex = _getPathSegmentIndexIfSubEntry(pkgDir, callerUri);
  if (endPathIndex == null) {
    throw "Unsupported path";
  }
  final String callerPkgDir = callerUri.pathSegments[endPathIndex];
  if (!_usDirs.contains(callerPkgDir)) {
    throw "Unsupported dir: $callerPkgDir -- expected one of $_usDirs.";
  }

  final Set<String> changedUsDirsSet = {};
  for (String path in changedFiles) {
    if (!path.startsWith("pkg/")) continue;
    List<String> paths = path.split("/");
    if (paths.length < 2) continue;
    if (_usDirs.contains(paths[1])) {
      changedUsDirsSet.add(paths[1]);
    }
  }

  if (changedUsDirsSet.isEmpty) {
    print("We have no changes.");
    return false;
  }

  final List<String> changedUsDirs = changedUsDirsSet.toList()..sort();
  if (changedUsDirs.first != callerPkgDir) {
    print("We expect this file to be called elsewhere which will do the work.");
    return false;
  }
  return true;
}

/// The `generated_files_up_to_date_git_test.dart` file imports
/// package:dart_style which imports package:analyzer --- so it's a lot of extra
/// stuff to compile (and thus an expensive script to start).
/// Therefore it's not done in the same way as the other things, but instead
/// launched separately.
bool _shouldRunGenerateFilesTest(List<String> changedFiles) {
  for (String path in changedFiles) {
    if (_generatedFilesUpToDateFiles.contains(path)) {
      return true;
    }
  }

  return false;
}

class DepsTestWork extends Work {
  DepsTestWork();

  @override
  String get name => "Deps test";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.DepsTest.index,
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new DepsTestWork();
  }
}

class ExplicitCreationWork extends Work {
  final Set<Uri> includedFiles;
  final Set<Uri> includedDirectoryUris;
  final Uri repoDir;

  ExplicitCreationWork(
      {required this.includedFiles,
      required this.includedDirectoryUris,
      required this.repoDir});

  @override
  String get name => "explicit creation test";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.ExplicitCreation.index,
      "includedFiles": includedFiles.map((e) => e.toString()).toList(),
      "includedDirectoryUris":
          includedDirectoryUris.map((e) => e.toString()).toList(),
      "repoDir": repoDir.toString(),
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new ExplicitCreationWork(
      includedFiles: Set<Uri>.from(
          (json["includedFiles"] as Iterable).map((e) => Uri.parse(e))),
      includedDirectoryUris: Set<Uri>.from(
          (json["includedDirectoryUris"] as Iterable).map((e) => Uri.parse(e))),
      repoDir: Uri.parse(json["repoDir"] as String),
    );
  }
}

class LintWork extends Work {
  final List<String> filters;
  final Uri repoDir;

  LintWork({required this.filters, required this.repoDir});

  @override
  String get name => "Lint test";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.Lint.index,
      "filters": filters,
      "repoDir": repoDir.toString(),
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new LintWork(
      filters: List<String>.from(json["filters"] as Iterable),
      repoDir: Uri.parse(json["repoDir"] as String),
    );
  }
}

class MessagesWork extends Work {
  final Uri repoDir;

  MessagesWork({required this.repoDir});

  @override
  String get name => "messages test";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.Messages.index,
      "repoDir": repoDir.toString(),
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new MessagesWork(
      repoDir: Uri.parse(json["repoDir"] as String),
    );
  }
}

class SpawnHelper {
  bool _spawned = false;
  late ReceivePort _receivePort;
  late SendPort _sendPort;
  late void Function(dynamic data) onData;
  final List<dynamic> data = [];

  void close() {
    if (!_spawned) throw "Not spawned!";
    _receivePort.close();
  }

  void send(Object? message) {
    if (!_spawned) throw "Not spawned!";
    _sendPort.send(message);
  }

  Future<void> spawn(Uri spawnUri, void Function(dynamic data) onData) async {
    if (_spawned) throw "Already spawned!";
    _spawned = true;
    this.onData = onData;
    _receivePort = ReceivePort();
    await Isolate.spawnUri(spawnUri, const [], _receivePort.sendPort);
    final Completer<SendPort> sendPortCompleter = Completer<SendPort>();
    _receivePort.listen((dynamic receivedData) {
      if (!sendPortCompleter.isCompleted) {
        sendPortCompleter.complete(receivedData);
      } else {
        onData(receivedData);
      }
    });
    _sendPort = await sendPortCompleter.future;
  }
}

class SpellNotSourceWork extends Work {
  final List<String> filters;
  final Uri repoDir;

  SpellNotSourceWork({required this.filters, required this.repoDir});

  @override
  String get name => "spell test not source";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.SpellingNotSource.index,
      "filters": filters,
      "repoDir": repoDir.toString(),
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new SpellNotSourceWork(
      filters: List<String>.from(json["filters"] as Iterable),
      repoDir: Uri.parse(json["repoDir"] as String),
    );
  }
}

class SpellSourceWork extends Work {
  final List<String> filters;
  final Uri repoDir;

  SpellSourceWork({required this.filters, required this.repoDir});

  @override
  String get name => "spell test source";

  @override
  Map<String, Object?> toJson() {
    return {
      "WorkTypeIndex": WorkEnum.SpellingSource.index,
      "filters": filters,
      "repoDir": repoDir.toString(),
    };
  }

  static Work fromJson(Map<String, Object?> json) {
    return new SpellSourceWork(
      filters: List<String>.from(json["filters"] as Iterable),
      repoDir: Uri.parse(json["repoDir"] as String),
    );
  }
}

sealed class Work {
  String get name;

  Map<String, Object?> toJson();

  static Work workFromJson(Map<String, Object?> json) {
    dynamic workTypeIndex = json["WorkTypeIndex"];
    if (workTypeIndex is! int ||
        workTypeIndex < 0 ||
        workTypeIndex >= WorkEnum.values.length) {
      throw "Cannot convert to a Work object.";
    }
    WorkEnum workType = WorkEnum.values[workTypeIndex];
    switch (workType) {
      case WorkEnum.ExplicitCreation:
        return ExplicitCreationWork.fromJson(json);
      case WorkEnum.Messages:
        return MessagesWork.fromJson(json);
      case WorkEnum.SpellingNotSource:
        return SpellNotSourceWork.fromJson(json);
      case WorkEnum.SpellingSource:
        return SpellSourceWork.fromJson(json);
      case WorkEnum.Lint:
        return LintWork.fromJson(json);
      case WorkEnum.DepsTest:
        return DepsTestWork.fromJson(json);
    }
  }
}

enum WorkEnum {
  ExplicitCreation,
  Messages,
  SpellingNotSource,
  SpellingSource,
  Lint,
  DepsTest,
}

extension on List<Work> {
  void addIfNotNull(Work? element) {
    if (element == null) return;
    add(element);
  }
}
