// Copyright (c) 2012, 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 'package:path/path.dart' as p;
import 'package:pub_semver/pub_semver.dart';

import 'exceptions.dart';
import 'git.dart' as git;
import 'ignore.dart';
import 'io.dart';
import 'log.dart' as log;
import 'package_name.dart';
import 'pubspec.dart';
import 'utils.dart';

/// A Package is a [Pubspec] and a directory where it belongs that can be used
/// for version solving or as a node in a package graph.
class Package {
  /// Compares [a] and [b] orders them by name then version number.
  ///
  /// This is normally used as a [Comparator] to pass to sort. This does not
  /// take a package's description or root directory into account, so multiple
  /// distinct packages may order the same.
  static int orderByNameAndVersion(Package a, Package b) {
    final name = a.name.compareTo(b.name);
    if (name != 0) return name;

    return a.version.compareTo(b.version);
  }

  /// The path to the directory containing the package.
  final String dir;

  /// A version of [dir] adapted for presenting in the terminal.
  ///
  /// If [dir] is just a parent directory like ../.. it gets replaced with
  /// the absolute dir.
  late final String presentationDir =
      p.isWithin(dir, '.') ? p.normalize(p.absolute(dir)) : dir;

  /// The name of the package.
  String get name => pubspec.name;

  /// The package's version.
  Version get version => pubspec.version;

  /// The parsed pubspec associated with this package.
  final Pubspec pubspec;

  /// The path to the entrypoint package's pubspec.
  String get pubspecPath => p.normalize(p.join(dir, 'pubspec.yaml'));

  /// The path to the entrypoint package's pubspec overrides file.
  String get pubspecOverridesPath =>
      p.normalize(p.join(dir, 'pubspec_overrides.yaml'));

  /// The (non-transitive) workspace packages.
  final List<Package> workspaceChildren;

  /// The transitive closure of [workspaceChildren] rooted at this package.
  ///
  /// Includes this package.
  Iterable<Package> get transitiveWorkspace sync* {
    final stack = [this];

    while (stack.isNotEmpty) {
      final current = stack.removeLast();
      yield current;
      // Because we pick from the end of the stack, elements are added in
      // reverse, such that they will be visited in the order they appear in the
      // list.
      stack.addAll(current.workspaceChildren.reversed);
    }
  }

  /// A collection of all overrides in the workspace.
  ///
  /// Should only be called on the workspace root.
  ///
  /// We only allow each package to be overridden once, so it is ok to collapse
  /// the overrides into a single map.
  late final Map<String, PackageRange> allOverridesInWorkspace = {
    for (final package in transitiveWorkspace)
      ...package.pubspec.dependencyOverrides,
  };

  /// The immediate dependencies this package specifies in its pubspec.
  Map<String, PackageRange> get dependencies => pubspec.dependencies;

  /// The immediate dev dependencies this package specifies in its pubspec.
  Map<String, PackageRange> get devDependencies => pubspec.devDependencies;

  /// All immediate dependencies this package specifies.
  ///
  /// This includes regular, dev dependencies, and overrides from this package.
  Map<String, PackageRange> get immediateDependencies {
    // Make sure to add overrides last so they replace normal dependencies.
    return {
      ...dependencies,
      ...devDependencies,
      ...pubspec.dependencyOverrides,
    };
  }

  /// Returns a list of paths to all Dart executables in
  /// this package's `bin` directory.
  List<String> get executablePaths {
    final binDir = p.join(dir, 'bin');
    if (!dirExists(binDir)) return <String>[];
    return [
      for (var executable in listDir(binDir, includeDirs: false))
        if (p.extension(executable) == '.dart')
          p.relative(executable, from: dir),
    ]..sort();
  }

  List<String> get executableNames =>
      executablePaths.map(p.basenameWithoutExtension).toList();

  /// Returns whether or not this package is in a Git repo.
  late final bool inGitRepo = computeInGitRepoCache();

  bool computeInGitRepoCache() {
    if (!git.isInstalled) {
      return false;
    } else {
      // If the entire package directory is ignored, don't consider it part of a
      // git repo. `git check-ignore` will return a status code of 0 for
      // ignored, 1 for not ignored, and 128 for not a Git repo.
      final result = runProcessSync(git.command!, [
        'check-ignore',
        '--quiet',
        '.',
      ], workingDir: dir);
      return result.exitCode == 1;
    }
  }

  /// Loads the package whose root directory is [dir].
  ///
  /// Will also load the workspace sub-packages of this package (recursively).
  ///
  /// [name] is the expected name of that package (e.g. the name given in the
  /// dependency), or `null` if the package being loaded is the entrypoint
  /// package.
  ///
  /// `pubspec_overrides.yaml` is only loaded if [withPubspecOverrides] is
  /// `true`.
  ///
  /// [loadPubspec] if given will be used to obtain a pubspec from a path. Also
  /// for the workspace children.
  ///
  /// This mechanism can be used to avoid loading pubspecs twice. It can also be
  /// used to override a pubspec in memory for trying out an alternative
  /// resolution.
  factory Package.load(
    String dir, {
    bool withPubspecOverrides = false,
    String? expectedName,
    required Pubspec Function(
      String path, {
      String? expectedName,
      required bool withPubspecOverrides,
    })
    loadPubspec,
  }) {
    final pubspec = loadPubspec(
      dir,
      withPubspecOverrides: withPubspecOverrides,
      expectedName: expectedName,
    );

    final workspacePackages =
        pubspec.workspace.map((workspacePath) {
          try {
            return Package.load(
              p.join(dir, workspacePath),
              loadPubspec: loadPubspec,
              withPubspecOverrides: withPubspecOverrides,
            );
          } on FileException catch (e) {
            final pubspecPath = p.join(dir, 'pubspec.yaml');
            throw FileException(
              '${e.message}\n'
              'That was included in the workspace of $pubspecPath.',
              e.path,
            );
          }
        }).toList();
    for (final package in workspacePackages) {
      if (package.pubspec.resolution != Resolution.workspace) {
        fail('''
${package.pubspecPath} is included in the workspace from ${p.join(dir, 'pubspec.yaml')}, but does not have `resolution: workspace`.

See $workspacesDocUrl for more information.
''');
      }
    }
    return Package(pubspec, dir, workspacePackages);
  }

  /// Creates a package with [pubspec] associated with [dir].
  ///
  /// For temporary resolution attempts [pubspec] does not have to correspond
  /// to the one at disk.
  Package(this.pubspec, this.dir, this.workspaceChildren);

  /// Given a relative path within this package, returns its absolute path.
  ///
  /// This is similar to `p.join(dir, part1, ...)`, except that subclasses may
  /// override it to report that certain paths exist elsewhere than within
  /// [dir].
  String path(
    String? part1, [
    String? part2,
    String? part3,
    String? part4,
    String? part5,
    String? part6,
    String? part7,
  ]) {
    return p.join(dir, part1, part2, part3, part4, part5, part6, part7);
  }

  /// Given an absolute path within this package (such as that returned by
  /// [path] or [listFiles]), returns it relative to the package root.
  String relative(String path) {
    return p.relative(path, from: dir);
  }

  static final _basicIgnoreRules = [
    '.*', // Don't include dot-files.
    '!.htaccess', // Include .htaccess anyways.
    'pubspec.lock',
    '!pubspec.lock/', // We allow a directory called pubspec lock.
    '/pubspec_overrides.yaml',
  ];

  /// Returns a list of files that are considered to be part of this package.
  ///
  /// If [beneath] is passed, this will only return files beneath that path,
  /// which is expected to be relative to the package's root directory. If
  /// [recursive] is true, this will return all files beneath that path;
  /// otherwise, it will only return files one level beneath it.
  ///
  /// This will take .pubignore and .gitignore files into account.
  ///
  /// If [dir] is inside a git repository, all ignore files from the repo root
  /// are considered.
  ///
  /// For each directory a .pubignore takes precedence over a .gitignore.
  ///
  /// Note that the returned paths will be always be below [dir], and will
  /// always start with [dir] (thus always be relative to the current working
  /// directory) or absolute id [dir] is absolute.
  ///
  /// To convert them to paths relative to the package root, use [p.relative].
  List<String> listFiles({
    String? beneath,
    bool recursive = true,
    bool includeDirs = false,
  }) {
    final packageDir = dir;
    final root = git.repoRoot(packageDir) ?? packageDir;
    beneath =
        p
            .toUri(
              p.normalize(
                p.relative(p.join(packageDir, beneath ?? '.'), from: root),
              ),
            )
            .path;
    if (beneath == './') beneath = '.';
    String resolve(String path) {
      if (Platform.isWindows) {
        return p.joinAll([root, ...p.posix.split(path)]);
      }
      return p.join(root, path);
    }

    /// Throws if [path] is a link that cannot resolve.
    ///
    /// Circular links will fail to resolve at some depth defined by the os.
    void verifyLink(String path) {
      final link = Link(path);
      if (link.existsSync()) {
        try {
          link.resolveSymbolicLinksSync();
        } on FileSystemException catch (e) {
          if (!link.existsSync()) {
            return;
          }
          throw DataException('Could not resolve symbolic link $path. $e');
        }
      }
    }

    /// We check each directory that it doesn't symlink-resolve to the
    /// symlink-resolution of any parent directory of itself. This avoids
    /// cycles.
    ///
    /// Cache the symlink resolutions here.
    final symlinkResolvedDirs = <String, String>{};
    String resolveDirSymlinks(String path) {
      return symlinkResolvedDirs[path] ??=
          Directory(path).resolveSymbolicLinksSync();
    }

    final result =
        Ignore.listFiles(
          beneath: beneath,
          listDir: (dir) {
            final resolvedDir = p.normalize(resolve(dir));
            verifyLink(resolvedDir);

            {
              final canonicalized = p.canonicalize(resolvedDir);
              final symlinkResolvedDir = resolveDirSymlinks(canonicalized);
              for (final parent in parentDirs(p.dirname(canonicalized))) {
                final symlinkResolvedParent = resolveDirSymlinks(parent);
                if (p.equals(symlinkResolvedDir, symlinkResolvedParent)) {
                  dataError('''
Pub does not support symlink cycles.

$symlinkResolvedDir => ${p.canonicalize(symlinkResolvedParent)}
''');
                }
              }
            }
            var contents = Directory(resolvedDir).listSync(followLinks: false);

            if (!recursive) {
              contents =
                  contents.where((entity) => entity is! Directory).toList();
            }
            return contents.map((entity) {
              final relative = p.relative(entity.path, from: root);
              if (Platform.isWindows) {
                return p.posix.joinAll(p.split(relative));
              }
              return relative;
            });
          },
          ignoreForDir: (dir) {
            final pubIgnore = resolve('$dir/.pubignore');
            final gitIgnore = resolve('$dir/.gitignore');
            final ignoreFile =
                fileExists(pubIgnore)
                    ? pubIgnore
                    : (fileExists(gitIgnore) ? gitIgnore : null);

            final rules = [
              if (dir == beneath) ..._basicIgnoreRules,
              if (ignoreFile != null) readTextFile(ignoreFile),
            ];
            return rules.isEmpty
                ? null
                : Ignore(
                  rules,
                  onInvalidPattern: (pattern, exception) {
                    log.warning(
                      '$ignoreFile had invalid pattern $pattern. '
                      '${exception.message}',
                    );
                  },
                  // Ignore case on macOS and Windows, because `git clone` and
                  // `git init` will set `core.ignoreCase = true` in the local
                  // local `.git/config` file for the repository.
                  //
                  // So on Windows and macOS most users will have
                  // case-insensitive behavior with `.gitignore`, hence, it
                  // seems reasonable to do the same when we interpret
                  // `.gitignore` and `.pubignore`.
                  //
                  // There are cases where a user may have case-sensitive
                  // behavior with `.gitignore` on Windows and macOS:
                  //
                  //  (A) The user has manually overwritten the repository
                  //      configuration setting `core.ignoreCase = false`.
                  //
                  //  (B) The git-clone or git-init command that create the
                  //      repository did not deem `core.ignoreCase = true` to be
                  //      appropriate. Documentation for [git-config]][1]
                  //      implies this might depend on whether or not the
                  //      filesystem is case sensitive: > If true, this option
                  //      enables various workarounds to > enable Git to work
                  //      better on filesystems that are not > case sensitive,
                  //      like FAT.
                  //      > ...
                  //      > The default is false, except git-clone[1] or
                  //      > git-init[1] will probe and set core.ignoreCase true
                  //      > if appropriate when the repository is created.
                  //
                  // In either case, it seems likely that users on Windows and
                  // macOS will prefer case-insensitive matching. We
                  // specifically know that some tooling will generate `.PDB`
                  // files instead of `.pdb`, see: [#3003][2]
                  //
                  // [1]:
                  // https://git-scm.com/docs/git-config/2.14.6#Documentation/git-config.txt-coreignoreCase
                  // [2]: https://github.com/dart-lang/pub/issues/3003
                  ignoreCase: Platform.isMacOS || Platform.isWindows,
                );
          },
          isDir: (dir) => dirExists(resolve(dir)),
          includeDirs: includeDirs,
        ).map(resolve).toList();
    for (final f in result) {
      verifyLink(f);
    }
    return result;
  }

  /// Applies [transform] to each package in the workspace and returns a derived
  /// package.
  Package transformWorkspace(Pubspec Function(Package) transform) {
    final workspace = {
      for (final package in transitiveWorkspace) package.dir: package,
    };
    return Package.load(
      dir,
      withPubspecOverrides: true,
      loadPubspec:
          (path, {expectedName, required withPubspecOverrides}) =>
              transform(workspace[path]!),
    );
  }
}

/// Reports an error if one or more of:
///
/// * The graph of the workspace rooted at [root] is not a tree.
/// * If a package name occurs twice.
/// * If two packages in the workspace override the same package name.
/// * A workspace package is overridden.
/// * A pubspec not included in the workspace exists in a directory
///   between the root and a workspace package.
void validateWorkspace(Package root) {
  if (root.workspaceChildren.isEmpty) return;

  /// Maps the `p.canonicalize`d dir of each workspace-child to its parent.
  final includedFrom = <String, String>{};
  final stack = [root];

  while (stack.isNotEmpty) {
    final current = stack.removeLast();
    for (final child in current.workspaceChildren) {
      final previous = includedFrom[p.canonicalize(child.dir)];
      if (previous != null) {
        if (previous == current.dir) {
          fail(
            '''
Packages can only be included in the workspace once.

`${p.join(child.dir, 'pubspec.yaml')}` is included twice into the workspace of `${p.join(current.dir, 'pubspec.yaml')}`''',
          );
        }
        fail('''
Packages can only be included in the workspace once.

`${p.join(child.dir, 'pubspec.yaml')}` is included in the workspace, both from:
* `${p.join(current.dir, 'pubspec.yaml')}` and
* `${p.join(previous, 'pubspec.yaml')}`.''');
      }
      includedFrom[p.canonicalize(child.dir)] = current.dir;
    }
    stack.addAll(current.workspaceChildren);
  }

  // Check that the workspace doesn't contain two packages with the same name!
  final namesSeen = <String, Package>{};
  for (final package in root.transitiveWorkspace) {
    final collision = namesSeen[package.name];
    if (collision != null) {
      fail('''
Workspace members must have unique names.
`${collision.pubspecPath}` and `${package.pubspecPath}` are both called "${package.name}".
''');
    }
    namesSeen[package.name] = package;
  }

  // Check that the workspace doesn't contain two overrides of the same package.
  // Also check that workspace packages are not overridden.
  final overridesSeen = <String, Package>{};
  for (final package in root.transitiveWorkspace) {
    for (final override in package.pubspec.dependencyOverrides.keys) {
      final collision = overridesSeen[override];
      if (collision != null) {
        fail('''
The package `$override` is overridden in both:
package `${collision.name}` at `${collision.dir}` and '${package.name}' at `${package.dir}`.

Consider removing one of the overrides.
''');
      }
      overridesSeen[override] = package;

      if (namesSeen[override] case final Package overriddenWorkspacePackage) {
        fail('''
Cannot override workspace packages.

Package `$override` at `${overriddenWorkspacePackage.presentationDir}` is overridden in `${package.pubspecPath}`.
''');
      }
    }
  }

  // Check for pubspec.yaml files between the root and any workspace package.
  final visited = <String>{
    // By adding this to visited we will never go above the workspaceRoot.dir.
    p.canonicalize(root.dir),
  };
  for (final package in root.transitiveWorkspace
  // We don't want to look at the roots parents. The first package is always
  // the root, so skip that.
  .skip(1)) {
    // Run through all parent directories until we meet another workspace
    // package.
    for (final dir in parentDirs(package.dir).skip(1)) {
      // Stop if we meet another package directory.
      if (includedFrom.containsKey(p.canonicalize(dir))) {
        break;
      }
      if (!visited.add(p.canonicalize(dir))) {
        // We have been here before.
        break;
      }
      final pubspecCandidate = p.join(dir, 'pubspec.yaml');
      if (fileExists(pubspecCandidate)) {
        fail('''
The file `$pubspecCandidate` is located in a directory between the workspace root at
`${root.dir}` and a workspace package at `${package.dir}`. But is not a member of the
workspace.

This blocks the resolution of the package at `${package.dir}`.

Consider removing it.

See https://dart.dev/go/workspaces-stray-files for details.
''');
      }
    }
  }
}
