// 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:glob/glob.dart';
import 'package:glob/list_local_fs.dart';
import 'package:pub_semver/pub_semver.dart';

import 'exceptions.dart';
import 'git.dart' as git;
import 'ignore.dart';
import 'io.dart';
import 'language_version.dart';
import 'log.dart' as log;
import 'package_name.dart';
import 'path.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.expand((workspacePath) {
          final packages = <Package>[];
          var globHint = '';
          if (pubspec.languageVersion.supportsWorkspaceGlobs) {
            final Glob glob;
            try {
              glob = Glob(workspacePath);
            } on FormatException catch (e) {
              fail('Failed to parse glob `$workspacePath`. $e');
            }
            for (final globResult in glob.listSync(root: dir)) {
              final pubspecPath = p.join(globResult.path, 'pubspec.yaml');
              if (!fileExists(pubspecPath)) continue;
              packages.add(
                Package.load(
                  globResult.path,
                  loadPubspec: loadPubspec,
                  withPubspecOverrides: withPubspecOverrides,
                ),
              );
            }
          } else {
            final pubspecPath = p.join(dir, workspacePath, 'pubspec.yaml');
            if (!fileExists(pubspecPath)) {
              if (_looksLikeGlob(workspacePath)) {
                globHint = '''
\n\nGlob syntax is only supported from language version ${LanguageVersion.firstVersionWithWorkspaceGlobs}.
Consider changing the language version of ${p.join(dir, 'pubspec.yaml')} to ${LanguageVersion.firstVersionWithWorkspaceGlobs}.
''';
              }
            } else {
              packages.add(
                Package.load(
                  p.join(dir, _useBackSlashesOnWindows(workspacePath)),
                  loadPubspec: loadPubspec,
                  withPubspecOverrides: withPubspecOverrides,
                ),
              );
            }
          }
          if (packages.isEmpty) {
            fail('''
No workspace packages matching `$workspacePath`.
That was included in the workspace of `${p.join(dir, 'pubspec.yaml')}`.$globHint
''');
          }
          return packages;
        }).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.
''');
      }
    }
  }
}

bool _looksLikeGlob(String s) => Glob.quote(s) != s;
String _useBackSlashesOnWindows(String path) {
  if (Platform.isWindows) {
    return p.joinAll(p.split(path));
  }
  return path;
}
