// Copyright (c) 2021, 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:convert';

import 'package:analysis_server/src/services/pub/pub_api.dart';
import 'package:analysis_server/src/services/pub/pub_command.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/instrumentation/service.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;

/// Information about Pub packages that can be converted to/from JSON and
/// cached to disk.
class PackageDetailsCache {
  static const cacheVersion = 3;
  static const maxCacheAge = Duration(hours: 18);
  static const maxPackageDetailsRequestsInFlight = 5;

  /// Requests to write the cache from fetching packge details will be debounced
  /// by this duration to prevent many writes while the user may be cursoring
  /// though completion requests that will trigger fetching descriptions/versions.
  static const _writeCacheDebounceDuration = Duration(seconds: 3);

  final Map<String, PubPackage> packages;
  DateTime lastUpdatedUtc;

  PackageDetailsCache._(this.packages, DateTime lastUpdated)
      : lastUpdatedUtc = lastUpdated.toUtc();

  Duration get cacheTimeRemaining {
    final cacheAge = DateTime.now().toUtc().difference(lastUpdatedUtc);
    final cacheTimeRemaining = maxCacheAge - cacheAge;
    return cacheTimeRemaining < Duration.zero
        ? Duration.zero
        : cacheTimeRemaining;
  }

  Map<String, Object> toJson() {
    return {
      'version': cacheVersion,
      'lastUpdated': lastUpdatedUtc.toIso8601String(),
      'packages': packages.values.toList(),
    };
  }

  static PackageDetailsCache empty() {
    return PackageDetailsCache._({}, DateTime.utc(2000));
  }

  static PackageDetailsCache fromApiResults(List<PubApiPackage> apiPackages) {
    final packages = Map.fromEntries(apiPackages.map((package) =>
        MapEntry(package.packageName, PubPackage.fromName(package))));

    return PackageDetailsCache._(packages, DateTime.now().toUtc());
  }

  /// Deserializes cached package data from JSON.
  ///
  /// If the JSON version does not match the current version, will return null.
  static PackageDetailsCache? fromJson(Map<String, Object?> json) {
    if (json['version'] != cacheVersion) {
      return null;
    }

    final packagesJson = json['packages'];
    if (packagesJson is! List<Object?>) {
      return null;
    }

    final packages = <PubPackage>[];
    for (final packageJson in packagesJson) {
      if (packageJson is! Map<String, Object?>) {
        return null;
      }
      final nameJson = packageJson['packageName'];
      if (nameJson is! String) {
        return null;
      }
      packages.add(PubPackage.fromJson(packageJson));
    }

    final packageMap = Map.fromEntries(
      packages.map(
        (package) => MapEntry(package.packageName, package),
      ),
    );

    final lastUpdatedJson = json['lastUpdated'];
    if (lastUpdatedJson is! String) {
      return null;
    }
    final lastUpdated = DateTime.tryParse(lastUpdatedJson);
    if (lastUpdated == null) {
      return null;
    }

    return PackageDetailsCache._(packageMap, lastUpdated);
  }
}

/// Information about a single Pub package.
class PubPackage {
  String packageName;
  String? description;
  String? latestVersion;

  PubPackage.fromDetails(PubApiPackageDetails package)
      : packageName = package.packageName,
        description = package.description,
        latestVersion = package.latestVersion;

  PubPackage.fromJson(Map<String, Object?> json)
      : packageName = json['packageName'] as String,
        description = json['description'] as String?,
        latestVersion = json['latestVersion'] as String?;

  PubPackage.fromName(PubApiPackage package)
      : packageName = package.packageName;

  Map<String, Object> toJson() {
    return {
      'packageName': packageName,
      if (description != null) 'description': description!,
      if (latestVersion != null) 'latestVersion': latestVersion!,
    };
  }
}

/// A service for providing Pub package information.
///
/// Uses a [PubApi] to communicate with the Pub API and a [PubCommand] to
/// interact with the local `pub` command.
///
/// Expensive results are cached to disk using [resourceProvider].
class PubPackageService {
  final InstrumentationService _instrumentationService;
  final PubApi _api;

  /// A wrapper over the "pub" command line too.
  ///
  /// This can be null when not running on a real file system because it may
  /// try to interact with folders that don't really exist.
  final PubCommand? _command;

  Timer? _nextPackageNameListRequestTimer;
  Timer? _nextWriteDiskCacheTimer;

  /// [ResourceProvider] used for accessing the disk for caches and checking
  /// project types. This will be a [PhysicalResourceProvider] outside of tests.
  final ResourceProvider resourceProvider;

  /// The current cache of package information. Initially `null`, but
  /// overwritten after first read of cache from disk or fetch from the API.
  @visibleForTesting
  PackageDetailsCache? packageCache;

  int _packageDetailsRequestsInFlight = 0;

  /// A cache of version numbers from running the "pub outdated" command used
  /// for completion in pubspec.yaml.
  final _pubspecPackageVersions =
      <String, Map<String, PubOutdatedPackageDetails>>{};

  PubPackageService(this._instrumentationService, this.resourceProvider,
      this._api, this._command);

  /// Gets the last set of package results from the Pub API or an empty List if
  /// no results.
  ///
  /// This data is used for completion of package names in pubspec.yaml
  /// and for clients that support lazy resolution of completion items may also
  /// include their descriptions and/or version numbers.
  List<PubPackage> get cachedPackages =>
      packageCache?.packages.values.toList() ?? [];

  @visibleForTesting
  bool get isPackageNamesTimerRunning =>
      _nextPackageNameListRequestTimer != null;

  @visibleForTesting
  File get packageCacheFile {
    final cacheFolder = resourceProvider
        .getStateLocation('.pub-package-details-cache')!
      ..create();
    return cacheFolder.getChildAssumingFile('packages.json');
  }

  /// Begins preloading caches for package names and pub versions.
  void beginCachePreloads(List<String> pubspecs) {
    beginPackageNamePreload();
    for (final pubspec in pubspecs) {
      fetchPackageVersionsViaPubOutdated(pubspec, pubspecWasModified: false);
    }
  }

  /// Begin a timer to pre-load and update the package name list if one has not
  /// already been started.
  void beginPackageNamePreload() {
    if (isPackageNamesTimerRunning) {
      return;
    }

    // If first time, try to read from disk.
    var cache = packageCache;
    if (cache == null) {
      cache ??= readDiskCache() ?? PackageDetailsCache.empty();
      packageCache = cache;
    }

    // If there is no queued request, initialize one when the current cache expires.
    _nextPackageNameListRequestTimer ??=
        Timer(cache.cacheTimeRemaining, _fetchFromServer);
  }

  /// Gets the latest cached package version fetched from the Pub API for the
  /// package [packageName].
  String? cachedPubApiLatestVersion(String packageName) =>
      packageCache?.packages[packageName]?.latestVersion;

  /// Gets the package versions cached using "pub outdated" for the package
  /// [packageName] for the project using [pubspecPath].
  ///
  /// Versions in here might only be available for packages that are in the
  /// pubspec on disk. Newly-added packages in the overlay might not be
  /// available.
  PubOutdatedPackageDetails? cachedPubOutdatedVersions(
      String pubspecPath, String packageName) {
    final pubspecCache = _pubspecPackageVersions[pubspecPath];
    return pubspecCache != null ? pubspecCache[packageName] : null;
  }

  /// Begin a request to pre-load package versions using the "pub outdated"
  /// command.
  ///
  /// If [pubspecWasModified] is true, the command will always be run. Otherwise it
  /// will only be run if data is not already cached.
  Future<void> fetchPackageVersionsViaPubOutdated(String pubspecPath,
      {required bool pubspecWasModified}) async {
    final pubCommand = _command;
    if (pubCommand == null) {
      return;
    }

    // If we already have a cache for the file and it was not modified (only
    // opened) we do not need to re-run the command.
    if (!pubspecWasModified &&
        _pubspecPackageVersions.containsKey(pubspecPath)) {
      return;
    }

    // Check if this pubspec is inside a DEPS-managed folder, and if so
    // just cache an empty set of results since Pub is not managing
    // dependencies.
    if (_hasAncestorDEPSFile(pubspecPath)) {
      _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
      return;
    }

    final results = await pubCommand.outdatedVersions(pubspecPath);
    final cache = _pubspecPackageVersions.putIfAbsent(pubspecPath, () => {});
    for (final package in results) {
      // We use the versions from the "pub outdated" results but only cache them
      // in-memory for this specific pubspec, as the resolved version may be
      // restricted by constraints/dependencies in the pubspec. The "pub"
      // command does caching of the JSON versions to make "pub outdated" fast.
      cache[package.packageName] = package;
    }
  }

  /// Clears package caches for [pubspecPath].
  ///
  /// Does not remove other caches that are not pubspec-specific (for example
  /// the latest version pulled directly from the Pub API independant of
  /// pubspec).
  Future<void> flushPackageCaches(String pubspecPath) async {
    _pubspecPackageVersions.remove(pubspecPath);
  }

  /// Gets package details for package [packageName].
  ///
  /// If the package details are not cached, will call the Pub API and cache
  /// the result. Results are cached for the same period as the main package
  /// list cache - that is, when the package list cache expires, all cached
  /// package details will go with it.
  Future<PubPackage?> packageDetails(String packageName) async {
    var packageData = packageCache?.packages[packageName];
    // If we don't have the version for this package, we don't have its full details.
    if (packageData?.latestVersion == null &&
        // Limit the number of package details requests that can be in-flight at
        // once since an editor may send many of these requests as the user
        // cursors through the results (a good editor will cancel the resolve
        // requests, but we may have already started the requests synchronously
        // before handling a cancellation).
        _packageDetailsRequestsInFlight <=
            PackageDetailsCache.maxPackageDetailsRequestsInFlight) {
      _packageDetailsRequestsInFlight++;
      try {
        final details = await _api.packageInfo(packageName);
        if (details != null) {
          packageData = PubPackage.fromDetails(details);
          packageCache?.packages[packageName] = packageData;
          _writeDiskCacheDebounced();
        }
      } finally {
        _packageDetailsRequestsInFlight--;
      }
    }
    return packageData;
  }

  @visibleForTesting
  PackageDetailsCache? readDiskCache() {
    final file = packageCacheFile;
    if (!file.exists) {
      return null;
    }
    try {
      final contents = file.readAsStringSync();
      final json = jsonDecode(contents);
      if (json is Map<String, Object?>) {
        return PackageDetailsCache.fromJson(json);
      } else {
        return null;
      }
    } catch (e) {
      _instrumentationService.logError('Error reading pub cache file: $e');
      return null;
    }
  }

  void shutdown() {
    _nextPackageNameListRequestTimer?.cancel();
    _command?.shutdown();
  }

  @visibleForTesting
  void writeDiskCache([PackageDetailsCache? cache]) {
    cache ??= packageCache;
    if (cache == null) {
      return;
    }
    final file = packageCacheFile;
    file.writeAsStringSync(jsonEncode(cache.toJson()));
  }

  Future<void> _fetchFromServer() async {
    try {
      final packages = await _api.allPackages();

      // If we never got a valid response, just skip until the next refresh.
      if (packages == null) {
        return;
      }

      final packageCache = PackageDetailsCache.fromApiResults(packages);
      this.packageCache = packageCache;
      writeDiskCache();
    } catch (e) {
      _instrumentationService.logError('Failed to fetch packages from Pub: $e');
    } finally {
      _nextPackageNameListRequestTimer =
          Timer(PackageDetailsCache.maxCacheAge, _fetchFromServer);
    }
  }

  /// Checks whether there is a DEPS file in any folder walking up from the
  /// pubspec at [pubspecPath].
  bool _hasAncestorDEPSFile(String pubspecPath) {
    var folder = path.dirname(pubspecPath);
    do {
      if (resourceProvider.getFile(path.join(folder, 'DEPS')).exists) {
        return true;
      }
      folder = path.dirname(folder);
    } while (folder != path.dirname(folder));
    return false;
  }

  /// Writes the package cache to disk after
  /// [PackageDetailsCache._writeCacheDebounceDuration] has elapsed, restarting
  /// the timer each time this method is called.
  void _writeDiskCacheDebounced() {
    _nextWriteDiskCacheTimer?.cancel();
    _nextWriteDiskCacheTimer =
        Timer(PackageDetailsCache._writeCacheDebounceDuration, writeDiskCache);
  }
}
