// Copyright (c) 2019, 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.

/// This library defines how `modular_test` converts the contents of a folder
/// into a modular test. At this time, the logic in this library assumes this is
/// only used within the Dart SDK repo.
///
/// A modular test folder contains:
///   * individual .dart files, each file is considered a module. A
///   `main.dart` file is required as the entry point of the test.
///   * subfolders: each considered a module with multiple files
///   * a modules.yaml file: a specification of dependencies between modules.
///     The format is described in `test_specification_parser.dart`.
library;

import 'dart:io';
import 'suite.dart';
import 'test_specification_parser.dart';
import 'find_sdk_root.dart';

/// Returns the [ModularTest] associated with a folder under [uri].
///
/// After scanning the contents of the folder, this method creates a
/// [ModularTest] that contains only modules that are reachable from the main
/// module.  This method runs several validations including that modules don't
/// have conflicting names, that the default packages are always visible, and
/// that modules do not contain cycles.
Future<ModularTest> loadTest(Uri uri) async {
  var folder = Directory.fromUri(uri);
  var testUri = folder.uri; // normalized in case the trailing '/' was missing.
  Uri root = await findRoot();
  final defaultTestSpecification = parseTestSpecification(_defaultPackagesSpec);
  Set<String> defaultPackages = defaultTestSpecification.packages.keys.toSet();
  Module sdkModule = await _createSdkModule(root);
  Map<String, Module> modules = {'sdk': sdkModule};
  String? specString;
  Module? mainModule;
  var entries = folder.listSync(recursive: false).toList()
    // Sort to avoid dependency on file system order.
    ..sort(_compareFileSystemEntity);
  for (var entry in entries) {
    var entryUri = entry.uri;
    if (entry is File) {
      var fileName = entryUri.path.substring(testUri.path.length);
      if (fileName.endsWith('.dart')) {
        var moduleName = fileName.substring(0, fileName.indexOf('.dart'));
        if (moduleName == 'sdk') {
          return _invalidTest(
            "The file '$fileName' defines a module called "
            "'$moduleName' which conflicts with the sdk module "
            "that is provided by default.",
          );
        }
        if (defaultPackages.contains(moduleName)) {
          return _invalidTest(
            "The file '$fileName' defines a module called "
            "'$moduleName' which conflicts with a package by the same name "
            "that is provided by default.",
          );
        }
        if (modules.containsKey(moduleName)) {
          return _moduleConflict(fileName, modules[moduleName]!, testUri);
        }
        var relativeUri = Uri.parse(fileName);
        var isMain = moduleName == 'main';
        var module = Module(
          moduleName,
          [],
          testUri,
          [relativeUri],
          mainSource: isMain ? relativeUri : null,
          isMain: isMain,
          packageBase: Uri.parse('.'),
        );
        if (isMain) mainModule = module;
        modules[moduleName] = module;
      } else if (fileName == 'modules.yaml') {
        specString = await entry.readAsString();
      }
    } else {
      assert(entry is Directory);
      var path = entryUri.path;
      var moduleName = path.substring(testUri.path.length, path.length - 1);
      if (moduleName == 'sdk') {
        return _invalidTest(
          "The folder '$moduleName' defines a module "
          "which conflicts with the sdk module "
          "that is provided by default.",
        );
      }
      if (defaultPackages.contains(moduleName)) {
        return _invalidTest(
          "The folder '$moduleName' defines a module "
          "which conflicts with a package by the same name "
          "that is provided by default.",
        );
      }
      if (modules.containsKey(moduleName)) {
        return _moduleConflict(moduleName, modules[moduleName]!, testUri);
      }
      var sources = await _listModuleSources(entryUri);
      modules[moduleName] = Module(
        moduleName,
        [],
        testUri,
        sources,
        packageBase: Uri.parse('$moduleName/'),
      );
    }
  }
  if (specString == null) {
    return _invalidTest("modules.yaml file is missing");
  }
  if (mainModule == null) {
    return _invalidTest("main module is missing");
  }

  TestSpecification spec = parseTestSpecification(specString);
  for (final name in defaultPackages) {
    if (spec.packages.containsKey(name)) {
      _invalidTest(
        ".packages file defines a conflicting entry for package '$name'.",
      );
    }
  }
  await _addModulePerPackage(defaultTestSpecification.packages, root, modules);
  await _addModulePerPackage(spec.packages, testUri, modules);
  _attachDependencies(spec.dependencies, modules);
  _attachDependencies(defaultTestSpecification.dependencies, modules);
  _addSdkDependencies(modules, sdkModule);
  _detectCyclesAndRemoveUnreachable(modules, mainModule);
  var sortedModules = modules.values.toList()
    ..sort((a, b) => a.name.compareTo(b.name));
  var sortedFlags = spec.flags.toList()..sort();
  return ModularTest(sortedModules, mainModule, sortedFlags);
}

/// Returns all source files recursively found in a folder as relative URIs.
Future<List<Uri>> _listModuleSources(Uri root) async {
  List<Uri> sources = [];
  Directory folder = Directory.fromUri(root);
  int baseUriPrefixLength = folder.parent.uri.path.length;
  await for (var file in folder.list(recursive: true)) {
    var path = file.uri.path;
    if (path.endsWith('.dart')) {
      sources.add(Uri.parse(path.substring(baseUriPrefixLength)));
    }
  }
  return sources..sort((a, b) => a.path.compareTo(b.path));
}

/// Add links between modules based on the provided dependency map.
void _attachDependencies(
  Map<String, List<String>> dependencies,
  Map<String, Module> modules,
) {
  dependencies.forEach((name, moduleDependencies) {
    final module = modules[name];
    if (module == null) {
      _invalidTest(
        "declared dependencies for a nonexistent module named '$name'",
      );
    }
    if (module.dependencies.isNotEmpty) {
      _invalidTest("Module dependencies have already been declared on $name.");
    }
    for (var dependencyName in moduleDependencies) {
      final moduleDependency = modules[dependencyName];
      if (moduleDependency == null) {
        _invalidTest(
          "'$name' declares a dependency on a nonexistent module "
          "named '$dependencyName'",
        );
      }
      module.dependencies.add(moduleDependency);
    }
  });
}

/// Make every module depend on the sdk module.
void _addSdkDependencies(Map<String, Module> modules, Module sdkModule) {
  for (var module in modules.values) {
    if (module != sdkModule) {
      module.dependencies.add(sdkModule);
    }
  }
}

/// Create a module for each package dependency.
Future<void> _addModulePerPackage(
  Map<String, String> packages,
  Uri configRoot,
  Map<String, Module> modules,
) async {
  for (var packageName in packages.keys) {
    var module = modules[packageName];
    if (module != null) {
      module.isPackage = true;
    } else {
      var packageLibUri = configRoot.resolve(packages[packageName]!);
      var packageRootUri = Directory.fromUri(packageLibUri).parent.uri;
      var sources = await _listModuleSources(packageLibUri);
      // TODO(sigmund): validate that we don't use a different alias for a
      // module that is part of the test (package name and module name should
      // match).
      modules[packageName] = Module(
        packageName,
        [],
        packageRootUri,
        sources,
        isPackage: true,
        packageBase: Uri.parse('lib/'),
        isShared: true,
      );
    }
  }
}

Future<Module> _createSdkModule(Uri root) async {
  List<Uri> sources = [Uri.parse('sdk/lib/libraries.json')];

  // Include all dart2js, ddc, vm library sources and patch files.
  // Note: we don't extract the list of files from the libraries.json because
  // it doesn't list files that are transitively imported.
  var sdkLibrariesAndPatchesRoots = ['sdk/lib/'];
  for (var path in sdkLibrariesAndPatchesRoots) {
    var dir = Directory.fromUri(root.resolve(path));
    await for (var file in dir.list(recursive: true)) {
      if (file is File && file.path.endsWith(".dart")) {
        sources.add(Uri.parse(file.uri.path.substring(root.path.length)));
      }
    }
  }
  sources.sort((a, b) => a.path.compareTo(b.path));
  return Module('sdk', [], root, sources, isSdk: true, isShared: true);
}

/// Trim the set of modules, and detect cycles while we are at it.
void _detectCyclesAndRemoveUnreachable(
  Map<String, Module> modules,
  Module main,
) {
  Set<Module> visiting = {};
  Set<Module> visited = {};

  helper(Module current) {
    if (!visiting.add(current)) {
      _invalidTest("module '${current.name}' has a dependency cycle.");
    }
    if (visited.add(current)) {
      current.dependencies.forEach(helper);
    }
    visiting.remove(current);
  }

  helper(main);
  Set<String> toKeep = visited.map((m) => m.name).toSet();
  List<String> toRemove = modules.keys
      .where((name) => !toKeep.contains(name))
      .toList();
  toRemove.forEach(modules.remove);
}

/// Specifies the dependencies of all packages in [_defaultPackagesInput]. This
/// string needs to be updated if dependencies between those packages changes
/// (which is rare).
// TODO(sigmund): consider either computing this from the pubspec files or the
// import graph, or adding tests that validate this is always up to date.
String _defaultPackagesSpec = '''
dependencies:
  expect: [meta, smith]
  smith: []
  meta: []
  collection: []
packages:
  expect: pkg/expect/lib
  smith: pkg/smith/lib
  meta: pkg/meta/lib
  collection: third_party/pkg/core/pkgs/collection/lib
''';

/// Report an conflict error.
Never _moduleConflict(String name, Module existing, Uri root) {
  var isFile = name.endsWith('.dart');
  var entryType = isFile ? 'file' : 'folder';

  var existingIsFile =
      existing.packageBase!.path == './' && existing.sources.length == 1;
  var existingEntryType = existingIsFile ? 'file' : 'folder';

  var existingName = existingIsFile
      ? existing.sources.single.pathSegments.last
      : existing.name;

  return _invalidTest(
    "The $entryType '$name' defines a module "
    "which conflicts with the module defined by the $existingEntryType "
    "'$existingName'.",
  );
}

Never _invalidTest(String message) {
  throw InvalidTestError(message);
}

class InvalidTestError extends Error {
  final String message;
  InvalidTestError(this.message);
  @override
  String toString() => "Invalid test: $message";
}

/// Comparator to sort directories before files.
int _compareFileSystemEntity(FileSystemEntity a, FileSystemEntity b) {
  if (a is Directory) {
    if (b is Directory) {
      return a.path.compareTo(b.path);
    } else {
      return -1;
    }
  } else {
    if (b is Directory) {
      return 1;
    } else {
      return a.path.compareTo(b.path);
    }
  }
}
