// Copyright (c) 2016, 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:async';
import 'dart:collection';

import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/file_source.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/context/packages.dart';
import 'package:analyzer/src/file_system/file_system.dart';
import 'package:analyzer/src/generated/sdk.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
import 'package:analyzer/src/util/uri.dart';
import 'package:analyzer/src/utilities/uri_cache.dart';
import 'package:analyzer/src/workspace/blaze_watcher.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';

/// Instances of the class `BlazeFileUriResolver` resolve `file` URI's by first
/// resolving file uri's in the expected way, and then by looking in the
/// corresponding generated directories.
class BlazeFileUriResolver extends ResourceUriResolver {
  final BlazeWorkspace workspace;

  BlazeFileUriResolver(this.workspace) : super(workspace.provider);

  @override
  Uri pathToUri(String path) {
    var pathContext = workspace.provider.pathContext;
    for (var genRoot in [...workspace.binPaths, workspace.genfiles]) {
      if (pathContext.isWithin(genRoot, path)) {
        String relative = pathContext.relative(path, from: genRoot);
        var writablePath = pathContext.join(workspace.root, relative);
        return pathContext.toUri(writablePath);
      }
    }
    return workspace.provider.pathContext.toUri(path);
  }

  @override
  Source? resolveAbsolute(Uri uri) {
    if (!ResourceUriResolver.isFileUri(uri)) {
      return null;
    }
    String filePath = fileUriToNormalizedPath(provider.pathContext, uri);
    var file = workspace.findFile(filePath);
    if (file != null) {
      return FileSource(file, uri);
    }
    return null;
  }
}

/// The [UriResolver] that can resolve `package` URIs in [BlazeWorkspace].
class BlazePackageUriResolver extends UriResolver {
  final BlazeWorkspace _workspace;
  final path.Context _context;

  /// The cache of absolute [Uri]s to [Source]s mappings.
  final Map<Uri, Source?> _sourceCache = HashMap();

  BlazePackageUriResolver(BlazeWorkspace workspace)
    : _workspace = workspace,
      _context = workspace.provider.pathContext;

  @override
  Uri? pathToUri(String path) {
    // Search in each root.
    for (var root in [
      ..._workspace.binPaths,
      _workspace.genfiles,
      _workspace.root,
    ]) {
      var uriParts = _restoreUriParts(root, path);
      if (uriParts != null) {
        return uriCache.parse('package:${uriParts[0]}/${uriParts[1]}');
      }
    }

    return null;
  }

  @override
  Source? resolveAbsolute(Uri uri) {
    if (_sourceCache.containsKey(uri)) {
      return _sourceCache[uri];
    }
    Source? source;
    var fullFilePath = resolveAbsolutePath(uri);
    if (fullFilePath != null) {
      var file = _workspace.findFile(fullFilePath);
      if (file != null) {
        return FileSource(file, uri);
      }
    }
    _sourceCache[uri] = source;
    return source;
  }

  String? resolveAbsolutePath(Uri uri) {
    if (uri.isScheme('file')) {
      var path = fileUriToNormalizedPath(_context, uri);
      var pathRelativeToRoot = _workspace._relativeToRoot(path);
      if (pathRelativeToRoot == null) return null;
      return _context.join(_workspace.root, pathRelativeToRoot);
    }
    if (!uri.isScheme('package')) {
      return null;
    }
    String uriPath = Uri.decodeComponent(uri.path);
    int slash = uriPath.indexOf('/');

    // If the path either starts with a slash or has no slash, it is invalid.
    if (slash < 1) {
      return null;
    }

    if (uriPath.contains('//') || uriPath.contains('..')) {
      return null;
    }

    String packageName = uriPath.substring(0, slash);

    String fileUriPart = uriPath.substring(slash + 1);
    if (fileUriPart.isEmpty) {
      return null;
    }

    String filePath = fileUriPart.replaceAll('/', _context.separator);

    if (!packageName.contains('.')) {
      return _context.join(
        _workspace.root,
        'third_party',
        'dart',
        packageName,
        'lib',
        filePath,
      );
    } else {
      String packagePath = packageName.replaceAll('.', _context.separator);
      return _context.join(_workspace.root, packagePath, 'lib', filePath);
    }
  }

  /// Restore [filePath] to its 'package:' URI parts.
  ///
  /// Returns `null` if [root] is null or if [filePath] is not within [root].
  List<String>? _restoreUriParts(String? root, String filePath) {
    path.Context context = _workspace.provider.pathContext;
    if (root != null && context.isWithin(root, filePath)) {
      String relative = context.relative(filePath, from: root);
      List<String> components = context.split(relative);
      if (components.length > 4 &&
          components[0] == 'third_party' &&
          components[1] == 'dart' &&
          components[3] == 'lib') {
        String packageName = components[2];
        String pathInLib = components.skip(4).join('/');
        return [packageName, pathInLib];
      } else {
        for (int i = components.length - 2; i >= 2; i--) {
          String component = components[i];
          if (component == 'lib') {
            String packageName = components.getRange(0, i).join('.');
            String pathInLib = components.skip(i + 1).join('/');
            return [packageName, pathInLib];
          }
        }
      }
    }
    return null;
  }
}

/// Information about a Blaze workspace.
class BlazeWorkspace extends Workspace
    implements WorkspaceWithDefaultAnalysisOptions {
  /// The name of the file that identifies a set of Blaze Targets.
  ///
  /// For Dart package purposes, a BUILD file identifies a package.
  static const String _buildFileName = 'BUILD';

  final ResourceProvider provider;

  /// The absolute workspace root path.
  ///
  /// It contains the `WORKSPACE` file or its parent contains the `READONLY`
  /// folder.
  @override
  final String root;

  /// The absolute paths to all `blaze-bin` folders.
  ///
  /// In practice, there is usually one "bin" path, and sometimes there are two,
  /// on distributed build systems. It is very rare to have more than two.
  final List<String> binPaths;

  /// The absolute path to the `blaze-genfiles` folder.
  final String genfiles;

  /// Sometimes `BUILD` files are not preserved, and `xyz.packages` files
  /// are created instead. But looking for them is expensive, so we want
  /// to avoid this in cases when `BUILD` files are always available.
  final bool _lookForBuildFileSubstitutes;

  /// If `true`, the language version for packages will be provided.
  ///
  /// If `false`, [BlazeWorkspacePackage.languageVersion] will return `null`,
  /// so that [Packages] will be used to get the language versions.
  ///
  /// See https://buganizer.corp.google.com/issues/279909837
  final bool _provideLanguageVersion;

  /// The language version for this workspace, `null` if cannot be read.
  final Version? _languageVersion;

  /// The cache of packages. The key is the directory path, the value is
  /// the corresponding package.
  final Map<String, BlazeWorkspacePackage> _directoryToPackage = {};

  final _blazeCandidateFiles = StreamController<BlazeSearchInfo>.broadcast();

  BlazeWorkspace._(
    this.provider,
    this.root,
    this.binPaths,
    this.genfiles, {
    required bool lookForBuildFileSubstitutes,
    required bool provideLanguageVersion,
  }) : _lookForBuildFileSubstitutes = lookForBuildFileSubstitutes,
       _provideLanguageVersion = provideLanguageVersion,
       _languageVersion =
           provideLanguageVersion ? _readLanguageVersion(provider, root) : null;

  /// Stream of files that we tried to find along with their potential or actual
  /// paths.
  Stream<BlazeSearchInfo> get blazeCandidateFiles =>
      _blazeCandidateFiles.stream;

  @override
  bool get isBlaze => true;

  @override
  BlazePackageUriResolver get packageUriResolver =>
      BlazePackageUriResolver(this);

  @override
  SourceFactory createSourceFactory(
    DartSdk? sdk,
    SummaryDataStore? summaryData,
  ) {
    List<UriResolver> resolvers = <UriResolver>[];
    if (sdk != null) {
      resolvers.add(DartUriResolver(sdk));
    }
    resolvers.add(packageUriResolver);
    resolvers.add(BlazeFileUriResolver(this));
    if (summaryData != null) {
      resolvers.add(InSummaryUriResolver(summaryData));
    }
    return SourceFactory(resolvers);
  }

  /// Return the file with the given [absolutePath], looking first into
  /// directories for generated files: `blaze-bin` and `blaze-genfiles`, and
  /// then into the workspace root. The file in the workspace root is returned
  /// even if it does not exist. Return `null` if the given [absolutePath] is
  /// not in the workspace [root].
  File? findFile(String absolutePath) {
    path.Context context = provider.pathContext;
    try {
      String relative = context.relative(absolutePath, from: root);
      if (relative == '.') {
        return null;
      }
      // First check genfiles and bin directories. Note that we always use the
      // symlinks and not the [binPaths] or [genfiles] to make sure we use the
      // files corresponding to the most recent build configuration and get
      // consistent view of all the generated files.
      var generatedCandidates = [
        'blaze-genfiles',
        'blaze-bin',
      ].map((prefix) => context.join(root, context.join(prefix, relative)));
      for (var path in generatedCandidates) {
        File file = provider.getFile(path);
        if (file.exists) {
          _blazeCandidateFiles.add(
            BlazeSearchInfo(relative, generatedCandidates.toList()),
          );
          return file;
        }
      }
      // Writable
      File writableFile = provider.getFile(absolutePath);
      if (writableFile.exists) {
        return writableFile;
      }
      // If we couldn't find the file, assume that it has not yet been
      // generated, so send an event with all the paths that we tried.
      _blazeCandidateFiles.add(
        BlazeSearchInfo(relative, generatedCandidates.toList()),
      );
      // Not generated, return the default one.
      return writableFile;
    } catch (_) {
      return null;
    }
  }

  @override
  BlazeWorkspacePackage? findPackageFor(String filePath) {
    path.Context context = provider.pathContext;
    var directoryPath = context.dirname(filePath);

    var cachedPackage = _directoryToPackage[directoryPath];
    if (cachedPackage != null) {
      return cachedPackage;
    }

    if (!context.isWithin(root, directoryPath)) {
      return null;
    }

    // Handle files which are given with their location in "blaze-bin", etc.
    // This does not typically happen during usual analysis, but it still could,
    // and it can come up in tests.
    for (var binPath in [genfiles, ...binPaths]) {
      if (context.isWithin(binPath, directoryPath)) {
        return findPackageFor(
          context.join(root, context.relative(filePath, from: binPath)),
        );
      }
    }

    /// Return the package rooted at [folder].
    BlazeWorkspacePackage? packageRootedAt(Folder folder) {
      var uriParts = packageUriResolver._restoreUriParts(
        root,
        '${folder.path}/lib/__fake__.dart',
      );
      String? packageName;
      if (uriParts != null && uriParts.isNotEmpty) {
        packageName = uriParts[0];
      }
      // TODO(srawlins): If [packageName] could not be derived from [uriParts],
      //  I imagine this should throw.
      if (packageName == null) {
        return null;
      }
      var package = BlazeWorkspacePackage(packageName, folder, this);
      _directoryToPackage[directoryPath] = package;
      return package;
    }

    var startFolder = provider.getFolder(directoryPath);
    for (var folder in startFolder.withAncestors) {
      if (folder.path.length < root.length) {
        // We've walked up outside of [root], so [path] is definitely not
        // defined in any package in this workspace.
        return null;
      }

      if (folder.getChildAssumingFile(_buildFileName).exists) {
        // Found the BUILD file, denoting a Dart package.
        return packageRootedAt(folder);
      }

      if (_hasBuildFileSubstitute(folder)) {
        return packageRootedAt(folder);
      }
    }

    return null;
  }

  /// In some distributed build environments, BUILD files are not preserved.
  /// We can still look for a ".packages" file in order to determine a
  /// package's root. A ".packages" file found in [folder]'s sister path
  /// under a "bin" path among [binPaths] denotes a Dart package.
  ///
  /// For example, if the [root] of this BlazeWorkspace is
  /// "/build/work/abc123/workspace" with two "bin" folders,
  /// "/build/work/abc123/workspace/blaze-out/host/bin/" and
  /// "/build/work/abc123/workspace/blaze-out/k8-opt/bin/", and [folder]
  /// is at "/build/work/abc123/workspace/foo/bar", then we  must look for a
  /// file ending in ".packages" in the folders
  /// "/build/work/abc123/workspace/blaze-out/host/bin/foo/bar" and
  /// "/build/work/abc123/workspace/blaze-out/k8-opt/bin/foo/bar".
  bool _hasBuildFileSubstitute(Folder folder) {
    if (!_lookForBuildFileSubstitutes) {
      return false;
    }

    path.Context context = provider.pathContext;

    // [folder]'s path, relative to [root]. For example, "foo/bar".
    String relative = context.relative(folder.path, from: root);

    for (String bin in binPaths) {
      Folder binChild = provider.getFolder(
        context.normalize(context.join(bin, relative)),
      );
      if (binChild.exists &&
          binChild.getChildren().any((c) => c.path.endsWith('.packages'))) {
        // [folder]'s sister folder within [bin] contains a ".packages" file.
        return true;
      }
    }

    return false;
  }

  String? _relativeToRoot(String p) {
    path.Context context = provider.pathContext;
    // genfiles
    if (context.isWithin(genfiles, p)) {
      return context.relative(p, from: genfiles);
    }
    // bin
    for (String bin in binPaths) {
      if (context.isWithin(bin, p)) {
        return context.relative(p, from: bin);
      }
    }
    // Not generated
    if (context.isWithin(root, p)) {
      return context.relative(p, from: root);
    }
    // Failed reverse lookup
    return null;
  }

  /// Find the Blaze workspace that contains the given [filePath].
  ///
  /// This method walks up the file system from [filePath], looking for various
  /// "marker" files which indicate a Blaze workspace.
  ///
  /// At each folder _f_ with parent _p_, starting with [filePath]:
  ///
  /// * If _f_ has a sibling folder named "READONLY", and that folder has a
  ///   child folder with the same name as _f_, then a [BlazeWorkspace] rooted at
  ///   _f_ is returned.
  /// * If _f_ has a child folder named "blaze-out", then a [BlazeWorkspace]
  ///   rooted at _f_ is returned.
  /// * If _f_ has a child file named [file_paths.blazeWorkspaceMarker], then
  ///   a [BlazeWorkspace] rooted at _f_ is returned.
  static BlazeWorkspace? find(
    ResourceProvider provider,
    String filePath, {
    bool lookForBuildFileSubstitutes = true,
    bool provideLanguageVersion = true,
  }) {
    var context = provider.pathContext;
    var startFolder = provider.getFolder(filePath);
    for (var folder in startFolder.withAncestors) {
      var parent = folder.parent;

      var blazeOutFolder = parent.getChildAssumingFolder('blaze-out');
      if (blazeOutFolder.exists) {
        // Found the "out" folder; must be a Blaze workspace.
        String root = parent.path;
        var binPaths = _findBinFolderPaths(parent);
        binPaths = binPaths..add(context.join(root, 'blaze-bin'));
        return BlazeWorkspace._(
          provider,
          root,
          binPaths,
          context.join(root, 'blaze-genfiles'),
          lookForBuildFileSubstitutes: lookForBuildFileSubstitutes,
          provideLanguageVersion: provideLanguageVersion,
        );
      }

      // Found the WORKSPACE file, must be a non-git workspace.
      if (folder.getChildAssumingFile(file_paths.blazeWorkspaceMarker).exists) {
        String root = folder.path;
        var binPaths = _findBinFolderPaths(folder);
        binPaths = binPaths..add(context.join(root, 'blaze-bin'));
        return BlazeWorkspace._(
          provider,
          root,
          binPaths,
          context.join(root, 'blaze-genfiles'),
          lookForBuildFileSubstitutes: lookForBuildFileSubstitutes,
          provideLanguageVersion: provideLanguageVersion,
        );
      }
    }

    return null;
  }

  /// Create the Blaze workspace with the given [root].
  ///
  /// This method should be used during build in google3, when we know for
  /// sure the workspace root, but [file_paths.blazeWorkspaceMarker] is not
  /// available.
  static BlazeWorkspace forBuild({required Folder root}) {
    var provider = root.provider;
    var blazeBin = root.getChildAssumingFolder('blaze-bin');
    var blazeGenfiles = root.getChildAssumingFolder('blaze-genfiles');

    var binPaths = _findBinFolderPaths(root);
    binPaths.add(blazeBin.path);

    return BlazeWorkspace._(
      provider,
      root.path,
      binPaths,
      blazeGenfiles.path,
      lookForBuildFileSubstitutes: true,
      provideLanguageVersion: true,
    );
  }

  /// Find the "bin" folder path, by searching for it.
  ///
  /// Depending on the environment we're working in (source code tree, build
  /// environment subtree of sources, local workspace, blaze), the "bin"
  /// folder may be available at a symlink found at `$root/blaze-bin/`. If that
  /// symlink is not available, then we must search the immediate folders found
  /// in `$root/blaze-out/` for folders named "bin".
  ///
  /// If no "bin" folder is found in any of those locations, empty list is
  /// returned.
  static List<String> _findBinFolderPaths(Folder root) {
    var out = root.getChildAssumingFolder('blaze-out');
    if (!out.exists) {
      return [];
    }

    List<String> binPaths = [];
    for (var child in out.getChildren().whereType<Folder>()) {
      // Children are folders denoting architectures and build flags, like
      // 'k8-opt', 'k8-fastbuild', perhaps 'host'.
      Folder possibleBin = child.getChildAssumingFolder('bin');
      if (possibleBin.exists) {
        binPaths.add(possibleBin.path);
      }
    }
    return binPaths;
  }

  /// Return the default language version of the workspace.
  ///
  /// Return `null` if cannot be read, for example because the file does not
  /// exist, or is not available in this build configuration (batch analysis).
  static Version? _readLanguageVersion(
    ResourceProvider resourceProvider,
    String rootPath,
  ) {
    var file = resourceProvider.getFile(
      resourceProvider.pathContext.joinAll([
        rootPath,
        'dart',
        'build_defs',
        'bzl',
        'language.bzl',
      ]),
    );

    String content;
    try {
      content = file.readAsStringSync();
    } on FileSystemException {
      return null;
    }

    var pattern = RegExp(r'(^|\s+)_version\s*=\s*"(\d+\.\d+)"');
    for (var match in pattern.allMatches(content)) {
      return Version.parse('${match.group(2)}.0');
    }

    return null;
  }
}

/// Information about a package defined in a [BlazeWorkspace].
///
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a [BlazeWorkspace].
class BlazeWorkspacePackage extends WorkspacePackageImpl {
  /// A prefix for any URI of a path in this package.
  final String _uriPrefix;

  @override
  final Folder root;

  @override
  final BlazeWorkspace workspace;

  List<String>? _enabledExperiments;
  Version? _languageVersion;

  BlazeWorkspacePackage(String packageName, this.root, this.workspace)
    : _uriPrefix = 'package:$packageName/';

  @override
  List<String>? get enabledExperiments {
    return _enabledExperiments;
  }

  @override
  Version? get languageVersion {
    if (!workspace._provideLanguageVersion) {
      return null;
    }
    return _languageVersion ?? workspace._languageVersion;
  }

  @override
  bool contains(Source source) {
    var uri = source.uri;
    if (uri.isScheme('package')) {
      return uri.toString().startsWith(_uriPrefix);
    }

    var path = source.fullName;
    return workspace.findPackageFor(path)?.root == root;
  }

  @override
  bool isInTestDirectory(File file) {
    return root.getChildAssumingFolder('test').contains(file.path);
  }

  @override
  // TODO(brianwilkerson): Implement this by looking in the BUILD file for 'deps'
  //  lists.
  Packages packagesAvailableTo(String libraryPath) => Packages.empty;

  @override
  bool sourceIsInPublicApi(Source source) {
    var filePath = filePathFromSource(source);
    if (filePath == null) return false;

    var libFolder = root.getChildAssumingFolder('lib');
    if (libFolder.contains(filePath)) {
      // A file in "$root/lib" is public iff it is not in "$root/lib/src".
      var libSrcFolder = libFolder.getChildAssumingFolder('src');
      return !libSrcFolder.contains(filePath);
    }

    var relativeRoot = workspace.provider.pathContext.relative(
      root.path,
      from: workspace.root,
    );
    for (var binPath in workspace.binPaths) {
      Folder bin = workspace.provider.getFolder(binPath);
      libFolder = bin
          .getChildAssumingFolder(relativeRoot)
          .getChildAssumingFolder('lib');
      if (libFolder.contains(filePath)) {
        // A file in "$bin/lib" is public iff it is not in "$bin/lib/src".
        var libSrcFolder = libFolder.getChildAssumingFolder('src');
        return !libSrcFolder.contains(filePath);
      }
    }

    libFolder = workspace.provider
        .getFolder(workspace.genfiles)
        .getChildAssumingFolder(relativeRoot)
        .getChildAssumingFolder('lib');
    if (libFolder.contains(filePath)) {
      // A file in "$genfiles/lib" is public iff it is not in
      // "$genfiles/lib/src".
      var libSrcFolder = libFolder.getChildAssumingFolder('src');
      return !libSrcFolder.contains(filePath);
    }

    return false;
  }
}
