// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

/// @docImport 'flutter_cache.dart';
/// @docImport 'runner/flutter_command.dart';
/// @docImport 'runner/flutter_command_runner.dart';
library;

import 'dart:async';
import 'dart:ffi' show Abi;
import 'dart:math' show max;

import 'package:crypto/crypto.dart';
import 'package:file/memory.dart';
import 'package:meta/meta.dart';
import 'package:process/process.dart';

import 'artifacts.dart';
import 'base/common.dart';
import 'base/context.dart';
import 'base/error_handling_io.dart';
import 'base/file_system.dart';
import 'base/io.dart'
    show
        HttpClient,
        HttpClientRequest,
        HttpClientResponse,
        HttpHeaders,
        HttpStatus,
        SocketException,
        Stdio;
import 'base/logger.dart';
import 'base/net.dart';
import 'base/os.dart' show OperatingSystemUtils;
import 'base/platform.dart';
import 'base/terminal.dart';
import 'base/user_messages.dart';
import 'base/utils.dart' show getElapsedAsSeconds, getSizeAsPlatformMB;
import 'convert.dart';
import 'features.dart';

const kFlutterRootEnvironmentVariableName =
    'FLUTTER_ROOT'; // should point to //flutter/ (root of flutter/flutter repo)
const kFlutterEngineEnvironmentVariableName =
    'FLUTTER_ENGINE'; // should point to //engine/src/ (root of flutter/engine repo)
const kSnapshotFileName = 'flutter_tools.snapshot'; // in //flutter/bin/cache/
const kFlutterToolsScriptFileName =
    'flutter_tools.dart'; // in //flutter/packages/flutter_tools/bin/
const kFlutterEnginePackageName = 'sky_engine';

/// A tag for a set of development artifacts that need to be cached.
class DevelopmentArtifact {
  const DevelopmentArtifact._(this.name, {this.feature});

  /// The name of the artifact.
  ///
  /// This should match the flag name in precache.dart.
  final String name;

  /// A feature to control the visibility of this artifact.
  final Feature? feature;

  /// Artifacts required for Android development.
  static const androidGenSnapshot = DevelopmentArtifact._(
    'android_gen_snapshot',
    feature: flutterAndroidFeature,
  );
  static const androidMaven = DevelopmentArtifact._(
    'android_maven',
    feature: flutterAndroidFeature,
  );

  // Artifacts used for internal builds.
  static const androidInternalBuild = DevelopmentArtifact._(
    'android_internal_build',
    feature: flutterAndroidFeature,
  );

  /// Artifacts required for iOS development.
  static const iOS = DevelopmentArtifact._('ios', feature: flutterIOSFeature);

  /// Artifacts required for web development.
  static const web = DevelopmentArtifact._('web', feature: flutterWebFeature);

  /// Artifacts required for desktop macOS.
  static const macOS = DevelopmentArtifact._('macos', feature: flutterMacOSDesktopFeature);

  /// Artifacts required for desktop Windows.
  static const windows = DevelopmentArtifact._('windows', feature: flutterWindowsDesktopFeature);

  /// Artifacts required for desktop Linux.
  static const linux = DevelopmentArtifact._('linux', feature: flutterLinuxDesktopFeature);

  /// Artifacts required for Fuchsia.
  static const fuchsia = DevelopmentArtifact._('fuchsia', feature: flutterFuchsiaFeature);

  /// Artifacts required for the Flutter Runner.
  static const flutterRunner = DevelopmentArtifact._(
    'flutter_runner',
    feature: flutterFuchsiaFeature,
  );

  /// Artifacts required for any development platform.
  ///
  /// This does not need to be explicitly returned from requiredArtifacts as
  /// it will always be downloaded.
  static const universal = DevelopmentArtifact._('universal');

  /// Artifacts which contain build information for the flutter tool.
  static const informative = DevelopmentArtifact._('informative');

  /// The values of DevelopmentArtifacts.
  static final values = <DevelopmentArtifact>[
    androidGenSnapshot,
    androidMaven,
    androidInternalBuild,
    iOS,
    web,
    macOS,
    windows,
    linux,
    fuchsia,
    universal,
    flutterRunner,
    informative,
  ];

  @override
  String toString() => 'Artifact($name)';
}

/// A wrapper around the `bin/cache/` directory.
///
/// This does not provide any artifacts by default. See [FlutterCache] for the default
/// artifact set.
///
/// ## Artifact mirrors
///
/// Some environments cannot reach the Google Cloud Storage buckets and CIPD due
/// to regional or corporate policies.
///
/// To enable Flutter users in these environments, the Flutter tool supports
/// custom artifact mirrors that the administrators of such environments may
/// provide. To use an artifact mirror, the user defines the [kFlutterStorageBaseUrl]
/// (`FLUTTER_STORAGE_BASE_URL`) environment variable that points to the mirror.
/// Flutter tool reads this variable and uses it instead of the default URLs.
///
/// For more details on specific URLs used to download artifacts, see
/// [storageBaseUrl] and [cipdBaseUrl].
class Cache {
  /// [_rootOverride] is configurable for testing.
  /// [artifacts] is configurable for testing.
  /// [artifactUpdater] is configurable for testing.
  Cache({
    @protected this._rootOverride,
    @protected List<ArtifactSet>? artifacts,
    @visibleForTesting ArtifactUpdater? artifactUpdater,
    required Logger logger,
    required FileSystem fileSystem,
    required Platform platform,
    required this._osUtils,
    this._stdio,
  }) : _logger = logger,
       _fileSystem = fileSystem,
       _platform = platform,
       _net = Net(logger: logger, platform: platform),
       _fsUtils = FileSystemUtils(fileSystem: fileSystem, platform: platform),
       _artifacts = artifacts ?? <ArtifactSet>[],
       _artifactUpdaterOverride = artifactUpdater;

  /// Create a [Cache] for testing.
  ///
  /// Defaults to a memory file system, fake platform,
  /// buffer logger, and no accessible artifacts.
  /// By default, the root cache directory path is "cache".
  factory Cache.test({
    Directory? rootOverride,
    List<ArtifactSet>? artifacts,
    ArtifactUpdater? artifactUpdater,
    Logger? logger,
    FileSystem? fileSystem,
    Platform? platform,
    Stdio? stdio,
    required ProcessManager processManager,
    Abi? currentAbi,
  }) {
    if (rootOverride?.fileSystem != null &&
        fileSystem != null &&
        rootOverride!.fileSystem != fileSystem) {
      throw ArgumentError(
        'If rootOverride and fileSystem are both non-null, '
            'rootOverride.fileSystem must be the same as fileSystem.',
        'fileSystem',
      );
    }
    fileSystem ??= rootOverride?.fileSystem ?? MemoryFileSystem.test();
    platform ??= FakePlatform(environment: <String, String>{});
    logger ??= BufferLogger.test();
    return Cache(
      rootOverride: rootOverride ?? fileSystem.currentDirectory,
      artifacts: artifacts ?? <ArtifactSet>[],
      artifactUpdater: artifactUpdater,
      logger: logger,
      fileSystem: fileSystem,
      platform: platform,
      stdio: stdio,
      osUtils: OperatingSystemUtils(
        fileSystem: fileSystem,
        logger: logger,
        platform: platform,
        processManager: processManager,
        currentAbi: currentAbi,
      ),
    );
  }

  final Logger _logger;
  final Platform _platform;
  final FileSystem _fileSystem;
  final OperatingSystemUtils _osUtils;
  OperatingSystemUtils get osUtils => _osUtils;
  final Directory? _rootOverride;
  final List<ArtifactSet> _artifacts;
  final Stdio? _stdio;
  final Net _net;
  final FileSystemUtils _fsUtils;

  final ArtifactUpdater? _artifactUpdaterOverride;
  late final ArtifactUpdater _artifactUpdater = _artifactUpdaterOverride ?? _createUpdater();

  @visibleForTesting
  @protected
  void registerArtifact(ArtifactSet artifactSet) {
    _artifacts.add(artifactSet);
  }

  /// This has to be lazy because it requires FLUTTER_ROOT to be initialized.
  ArtifactUpdater _createUpdater() {
    return ArtifactUpdater(
      operatingSystemUtils: _osUtils,
      logger: _logger,
      fileSystem: _fileSystem,
      tempStorage: getDownloadDir(),
      platform: _platform,
      httpClient: HttpClient(),
      allowedBaseUrls: <String>[storageBaseUrl, realmlessStorageBaseUrl, cipdBaseUrl],
      stdio: _stdio,
    );
  }

  static const _hostsBlockedInChina = <String>[
    'storage.googleapis.com',
    'chrome-infra-packages.appspot.com',
  ];

  // Initialized by FlutterCommandRunner on startup.
  // Explore making this field lazy to catch non-initialized access.
  static String? flutterRoot;

  /// Determine the absolute and normalized path for the root of the current
  /// Flutter checkout.
  ///
  /// This method has a series of fallbacks for determining the repo location. The
  /// first success will immediately return the root without further checks.
  ///
  /// The order of these tests is:
  ///   1. FLUTTER_ROOT environment variable contains the path.
  ///   2. Platform script is a data URI scheme, returning `../..` to support
  ///      tests run from `packages/flutter_tools`.
  ///   3. Platform script is package URI scheme, returning the grandgrandparent
  ///      directory of the package config file location from
  ///      `packages/flutter_tools/.dart_tool/package_config.json`.
  ///   4. Platform script file path is the snapshot path generated by `bin/flutter`,
  ///      returning the grandparent directory from `bin/cache`.
  ///   5. Platform script file name is the entrypoint in `packages/flutter_tools/bin/flutter_tools.dart`,
  ///      returning the 4th parent directory.
  ///   6. The current directory
  ///
  /// If an exception is thrown during any of these checks, an error message is
  /// printed and `.` is returned by default (6).
  static String defaultFlutterRoot({
    required Platform platform,
    required FileSystem fileSystem,
    required UserMessages userMessages,
  }) {
    String normalize(String path) {
      return fileSystem.path.normalize(fileSystem.path.absolute(path));
    }

    if (platform.environment.containsKey(kFlutterRootEnvironmentVariableName)) {
      return normalize(platform.environment[kFlutterRootEnvironmentVariableName]!);
    }
    try {
      if (platform.script.scheme == 'data') {
        return normalize('../..'); // The tool is running as a test.
      }
      final String Function(String) dirname = fileSystem.path.dirname;

      if (platform.script.scheme == 'package') {
        final String packageConfigPath = Uri.parse(platform.packageConfig!)
            .toFilePath(windows: platform.isWindows);
        return normalize(dirname(dirname(dirname(dirname(packageConfigPath)))));
      }

      if (platform.script.scheme == 'file') {
        final String script = platform.script.toFilePath(windows: platform.isWindows);
        if (fileSystem.path.basename(script) == kSnapshotFileName) {
          return normalize(dirname(dirname(fileSystem.path.dirname(script))));
        }
        if (fileSystem.path.basename(script) == kFlutterToolsScriptFileName) {
          return normalize(dirname(dirname(dirname(dirname(script)))));
        }
      }
    } on Exception catch (error) {
      // There is currently no logger attached since this is computed at startup.
      // ignore: avoid_print
      print(userMessages.runnerNoRoot('$error'));
    }
    return normalize('.');
  }

  // Whether to cache artifacts for all platforms. Defaults to only caching
  // artifacts for the current platform.
  bool includeAllPlatforms = false;

  // Names of artifacts which should be cached even if they would normally
  // be filtered out for the current platform.
  Set<String>? platformOverrideArtifacts;

  // Whether to cache the unsigned mac binaries. Defaults to caching the signed binaries.
  bool useUnsignedMacBinaries = false;

  // Whether the warning printed when a custom artifact URL is used is fatal.
  bool fatalStorageWarning = true;

  static RandomAccessFile? _lock;
  static var _lockEnabled = true;

  /// Turn off the [lock]/[releaseLock] mechanism.
  ///
  /// This is used by the tests since they run simultaneously and all in one
  /// process and so it would be a mess if they had to use the lock.
  @visibleForTesting
  static void disableLocking() {
    _lockEnabled = false;
  }

  /// Turn on the [lock]/[releaseLock] mechanism.
  ///
  /// This is used by the tests.
  @visibleForTesting
  static void enableLocking() {
    _lockEnabled = true;
  }

  /// Check if lock acquired, skipping FLUTTER_ALREADY_LOCKED reentrant checks.
  ///
  /// This is used by the tests.
  @visibleForTesting
  static bool isLocked() {
    return _lock != null;
  }

  /// Lock the cache directory.
  ///
  /// This happens while required artifacts are updated
  /// (see [FlutterCommandRunner.runCommand]).
  ///
  /// This uses normal POSIX flock semantics.
  Future<void> lock() async {
    if (!_lockEnabled) {
      return;
    }
    assert(_lock == null);
    final File lockFile = _fileSystem.file(
      _fileSystem.path.join(flutterRoot!, 'bin', 'cache', 'lockfile'),
    );
    try {
      _lock = lockFile.openSync(mode: FileMode.write);
    } on FileSystemException catch (e) {
      _logger.printError('Failed to open or create the artifact cache lockfile: "$e"');
      _logger.printError('Please ensure you have permissions to create or open ${lockFile.path}');
      throwToolExit('Failed to open or create the lockfile');
    }
    var locked = false;
    var printed = false;
    while (!locked) {
      try {
        _lock!.lockSync();
        locked = true;
      } on FileSystemException {
        if (!printed) {
          _logger.printTrace(
            'Waiting to be able to obtain lock of Flutter binary artifacts directory: ${_lock!.path}',
          );
          // This needs to go to stderr to avoid cluttering up stdout if a
          // parent process is collecting stdout (e.g. when calling "flutter
          // version --machine"). It's not really a "warning" though, so print it
          // in grey. Also, make sure that it isn't counted as a warning for
          // Logger.warningsAreFatal.
          _logger.printWarning(
            'Waiting for another flutter command to release the startup lock...',
            color: TerminalColor.grey,
            fatal: false,
          );
          printed = true;
        }
        await Future<void>.delayed(const Duration(milliseconds: 50));
      }
    }
  }

  /// Releases the lock.
  ///
  /// This happens automatically on startup (see [FlutterCommand.verifyThenRunCommand])
  /// after the command's required artifacts are updated.
  void releaseLock() {
    if (!_lockEnabled || _lock == null) {
      return;
    }
    _lock!.closeSync();
    _lock = null;
  }

  /// Checks if the current process owns the lock for the cache directory at
  /// this very moment; throws a [StateError] if it doesn't.
  void checkLockAcquired() {
    if (_lockEnabled &&
        _lock == null &&
        _platform.environment['FLUTTER_ALREADY_LOCKED'] != 'true') {
      throw StateError(
        'The current process does not own the lock for the cache directory. This is a bug in Flutter CLI tools.',
      );
    }
  }

  String get devToolsVersion {
    if (_devToolsVersion == null) {
      const devToolsDirPath = 'dart-sdk/bin/resources/devtools';
      final Directory devToolsDir = getCacheDir(devToolsDirPath, shouldCreate: false);
      if (!devToolsDir.existsSync()) {
        throw Exception('Could not find directory at ${devToolsDir.path}');
      }
      final versionFilePath = '${devToolsDir.path}/version.json';
      final File versionFile = _fileSystem.file(versionFilePath);
      if (!versionFile.existsSync()) {
        throw Exception('Could not find file at $versionFilePath');
      }
      final dynamic data = jsonDecode(versionFile.readAsStringSync());
      if (data is! Map<String, Object?>) {
        throw Exception(
          "Expected object of type 'Map<String, Object?>' but got one of type '${data.runtimeType}'",
        );
      }
      final Object? version = data['version'];
      if (version == null) {
        throw Exception('Could not parse DevTools version from $version');
      }
      if (version is! String) {
        throw Exception(
          "Could not parse DevTools version. Expected object of type 'String', but got one of type '${version.runtimeType}'",
        );
      }
      return _devToolsVersion = version;
    }
    return _devToolsVersion!;
  }

  String? _devToolsVersion;

  /// The current version of Dart used to build Flutter and run the tool.
  String get dartSdkVersion {
    if (_dartSdkVersion == null) {
      // Make the version string more customer-friendly.
      // Changes '2.1.0-dev.8.0.flutter-4312ae32' to '2.1.0 (build 2.1.0-dev.8.0 4312ae32)'
      final String justVersion = _platform.version.split(' ')[0];
      _dartSdkVersion = justVersion.replaceFirstMapped(RegExp(r'(\d+\.\d+\.\d+)(.+)'), (
        Match match,
      ) {
        final String noFlutter = match[2]!.replaceAll('.flutter-', ' ');
        return '${match[1]} (build ${match[1]}$noFlutter)';
      });
    }
    return _dartSdkVersion!;
  }

  String? _dartSdkVersion;

  /// The current version of Dart used to build Flutter and run the tool.
  String get dartSdkBuild {
    if (_dartSdkBuild == null) {
      // Make the version string more customer-friendly.
      // Changes '2.1.0-dev.8.0.flutter-4312ae32' to '2.1.0 (build 2.1.0-dev.8.0 4312ae32)'
      final String justVersion = _platform.version.split(' ')[0];
      _dartSdkBuild = justVersion.replaceFirstMapped(RegExp(r'(\d+\.\d+\.\d+)(.+)'), (Match match) {
        final String noFlutter = match[2]!.replaceAll('.flutter-', ' ');
        return '${match[1]}$noFlutter';
      });
    }
    return _dartSdkBuild!;
  }

  String? _dartSdkBuild;

  /// The current version of the Flutter engine the flutter tool will download.
  String get engineRevision {
    _engineRevision ??= getStampFor('engine');
    if (_engineRevision == null) {
      throwToolExit('Could not determine engine revision.');
    }
    return _engineRevision!;
  }

  String? _engineRevision;

  /// The "realm" for the storage URL.
  ///
  /// For production artifacts from Engine post-submit and release builds,
  /// this string will be empty, and the `storageBaseUrl` will be unmodified.
  /// When non-empty, this string will be appended to the `storageBaseUrl` after
  /// a '/'. For artifacts generated by Engine presubmits, the realm should be
  /// "flutter_archives_v2".
  String get storageRealm {
    _storageRealm ??= getRealmFor('engine');
    if (_storageRealm == null) {
      throwToolExit('Could not determine engine realm.');
    }
    return _storageRealm!;
  }

  String? _storageRealm;

  /// The base for URLs that store Flutter engine artifacts that are fetched
  /// during the installation of the Flutter SDK.
  ///
  /// By default the base URL is https://storage.googleapis.com. However, if
  /// `FLUTTER_STORAGE_BASE_URL` environment variable ([kFlutterStorageBaseUrl])
  /// is provided, the environment variable value is returned instead.
  ///
  /// See also:
  ///
  ///  * [cipdBaseUrl], which determines how CIPD artifacts are fetched.
  ///  * [Cache] class-level dartdocs that explain how artifact mirrors work.
  String get storageBaseUrl {
    String? overrideUrl = _platform.environment[kFlutterStorageBaseUrl];
    if (overrideUrl == null) {
      return storageRealm.isEmpty
          ? 'https://storage.googleapis.com'
          : 'https://storage.googleapis.com/$storageRealm';
    }
    // verify that this is a valid URI.
    overrideUrl = storageRealm.isEmpty ? overrideUrl : '$overrideUrl/$storageRealm';
    try {
      Uri.parse(overrideUrl);
    } on FormatException catch (err) {
      throwToolExit('"$kFlutterStorageBaseUrl" contains an invalid URL:\n$err');
    }
    _maybeWarnAboutStorageOverride(overrideUrl);
    return overrideUrl;
  }

  String get realmlessStorageBaseUrl {
    return storageRealm.isEmpty ? storageBaseUrl : storageBaseUrl.replaceAll('/$storageRealm', '');
  }

  /// The base for URLs that store Flutter engine artifacts in CIPD.
  ///
  /// For some platforms, such as Web and Fuchsia, CIPD artifacts are fetched
  /// during the installation of the Flutter SDK, in addition to those fetched
  /// from [storageBaseUrl].
  ///
  /// By default the base URL is https://chrome-infra-packages.appspot.com/dl.
  /// However, if `FLUTTER_STORAGE_BASE_URL` environment variable is provided
  /// ([kFlutterStorageBaseUrl]), then the following value is used:
  ///
  ///     FLUTTER_STORAGE_BASE_URL/flutter_infra_release/cipd
  ///
  /// See also:
  ///
  ///  * [storageBaseUrl], which determines how engine artifacts stored in the
  ///    Google Cloud Storage buckets are fetched.
  ///  * https://chromium.googlesource.com/infra/luci/luci-go/+/refs/heads/main/cipd,
  ///    which contains information about CIPD.
  ///  * [Cache] class-level dartdocs that explain how artifact mirrors work.
  String get cipdBaseUrl {
    final String? overrideUrl = _platform.environment[kFlutterStorageBaseUrl];
    if (overrideUrl == null) {
      return 'https://chrome-infra-packages.appspot.com/dl';
    }

    final Uri original;
    try {
      original = Uri.parse(overrideUrl);
    } on FormatException catch (err) {
      throwToolExit('"$kFlutterStorageBaseUrl" contains an invalid URL:\n$err');
    }

    final cipdOverride = original
        .replace(pathSegments: <String>[...original.pathSegments, 'flutter_infra_release', 'cipd'])
        .toString();
    return cipdOverride;
  }

  var _hasWarnedAboutStorageOverride = false;

  void _maybeWarnAboutStorageOverride(String overrideUrl) {
    if (_hasWarnedAboutStorageOverride) {
      return;
    }
    _logger.printWarning(
      'Flutter assets will be downloaded from $overrideUrl. Make sure you trust this source!',
      emphasis: true,
      fatal: false,
    );
    _hasWarnedAboutStorageOverride = true;
  }

  /// Return the top-level directory in the cache; this is `bin/cache`.
  Directory getRoot() {
    return _fileSystem.directory(
      _fileSystem.path.join(_rootOverride?.path ?? flutterRoot!, 'bin', 'cache'),
    );
  }

  String getHostPlatformArchName() {
    return _osUtils.hostPlatform.platformName;
  }

  /// Return a directory in the cache dir. For `pkg`, this will return `bin/cache/pkg`.
  ///
  /// When [shouldCreate] is true, the cache directory at [name] will be created
  /// if it does not already exist.
  Directory getCacheDir(String name, {bool shouldCreate = true}) {
    final Directory dir = _fileSystem.directory(_fileSystem.path.join(getRoot().path, name));
    if (!dir.existsSync() && shouldCreate) {
      dir.createSync(recursive: true);
      _osUtils.chmod(dir, '755');
    }
    return dir;
  }

  /// Return the top-level directory for artifact downloads.
  Directory getDownloadDir() => getCacheDir('downloads');

  /// Return the top-level mutable directory in the cache; this is `bin/cache/artifacts`.
  Directory getCacheArtifacts() => getCacheDir('artifacts');

  /// Location of LICENSE file.
  File getLicenseFile() => _fileSystem.file(_fileSystem.path.join(flutterRoot!, 'LICENSE'));

  /// Get a named directory from with the cache's artifact directory; for example,
  /// `material_fonts` would return `bin/cache/artifacts/material_fonts`.
  Directory getArtifactDirectory(String name) {
    return getCacheArtifacts().childDirectory(name);
  }

  MapEntry<String, String> get dyLdLibEntry {
    if (_dyLdLibEntry != null) {
      return _dyLdLibEntry!;
    }
    final paths = <String>[];
    for (final ArtifactSet artifact in _artifacts) {
      final Map<String, String> env = artifact.environment;
      if (!env.containsKey('DYLD_LIBRARY_PATH')) {
        continue;
      }
      final String path = env['DYLD_LIBRARY_PATH']!;
      if (path.isEmpty) {
        continue;
      }
      paths.add(path);
    }
    _dyLdLibEntry = MapEntry<String, String>('DYLD_LIBRARY_PATH', paths.join(':'));
    return _dyLdLibEntry!;
  }

  MapEntry<String, String>? _dyLdLibEntry;

  /// The web sdk has to be co-located with the dart-sdk so that they can share source
  /// code.
  Directory getWebSdkDirectory() {
    return getRoot().childDirectory('flutter_web_sdk');
  }

  String? getVersionFor(String artifactName) {
    final File versionFile = _fileSystem.file(
      _fileSystem.path.join(
        _rootOverride?.path ?? flutterRoot!,
        'bin',
        'internal',
        '$artifactName.version',
      ),
    );
    return versionFile.existsSync() ? versionFile.readAsStringSync().trim() : null;
  }

  // TODO(matanlurey): Remove the ability to do "generic" realms, and special case for engine.
  // https://github.com/flutter/flutter/issues/164315
  String? getRealmFor(String artifactName) {
    final File realmFile = _fileSystem.file(
      _fileSystem.path.join(
        _rootOverride?.path ?? flutterRoot!,
        'bin',
        'cache',
        '$artifactName.realm',
      ),
    );
    return realmFile.existsSync() ? realmFile.readAsStringSync().trim() : '';
  }

  /// Delete all stamp files maintained by the cache.
  void clearStampFiles() {
    try {
      getStampFileFor('flutter_tools').deleteSync();
      for (final ArtifactSet artifact in _artifacts) {
        final File file = getStampFileFor(artifact.stampName);
        ErrorHandlingFileSystem.deleteIfExists(file);
      }
    } on FileSystemException catch (err) {
      _logger.printWarning('Failed to delete some stamp files: $err');
    }
  }

  /// Read the stamp for [artifactName].
  ///
  /// If the file is missing or cannot be parsed, returns `null`.
  String? getStampFor(String artifactName) {
    final File stampFile = getStampFileFor(artifactName);
    if (!stampFile.existsSync()) {
      return null;
    }
    try {
      return stampFile.readAsStringSync().trim();
    } on FileSystemException {
      return null;
    }
  }

  void setStampFor(String artifactName, String version) {
    getStampFileFor(artifactName).writeAsStringSync(version);
  }

  File getStampFileFor(String artifactName) {
    return _fileSystem.file(_fileSystem.path.join(getRoot().path, '$artifactName.stamp'));
  }

  /// Returns `true` if either [entity] is older than the tools stamp or if
  /// [entity] doesn't exist.
  bool isOlderThanToolsStamp(FileSystemEntity entity) {
    final File flutterToolsStamp = getStampFileFor('flutter_tools');
    return _fsUtils.isOlderThanReference(entity: entity, referenceFile: flutterToolsStamp);
  }

  Future<bool> isUpToDate() async {
    for (final ArtifactSet artifact in _artifacts) {
      if (!await artifact.isUpToDate(_fileSystem)) {
        return false;
      }
    }
    return true;
  }

  /// Returns the list of artifacts that need updating from [requiredArtifacts].
  Future<List<ArtifactSet>> _collectArtifactsToUpdate(
    Set<DevelopmentArtifact> requiredArtifacts,
  ) async {
    final artifactsToUpdate = <ArtifactSet>[];
    final isLocalEngine = context.get<Artifacts>()?.localEngineInfo != null;

    for (final ArtifactSet artifact in _artifacts) {
      if (!requiredArtifacts.contains(artifact.developmentArtifact)) {
        _logger.printTrace('Artifact $artifact is not required, skipping update.');
        continue;
      }
      if (isLocalEngine && (artifact is EngineCachedArtifact || artifact.name == 'engine_stamp')) {
        _logger.printTrace(
          'Artifact $artifact is an engine artifact or stamp and local engine is provided, skipping update.',
        );
        continue;
      }
      if (await artifact.isUpToDate(_fileSystem)) {
        continue;
      }
      artifactsToUpdate.add(artifact);
    }
    return artifactsToUpdate;
  }

  /// Update the cache to contain all `requiredArtifacts`.
  Future<void> updateAll(Set<DevelopmentArtifact> requiredArtifacts, {bool offline = false}) async {
    if (!_lockEnabled) {
      return;
    }

    final List<ArtifactSet> artifactsToUpdate = await _collectArtifactsToUpdate(requiredArtifacts);

    if (artifactsToUpdate.isEmpty) {
      return;
    }

    // Download artifacts and display progress
    final int total = artifactsToUpdate
        .where((ArtifactSet artifact) => artifact.downloadCount > 0)
        .length;
    var current = 0;
    try {
      for (final artifact in artifactsToUpdate) {
        if (artifact.downloadCount > 0) {
          current += 1;

          // Set progress context for the artifact updater
          _artifactUpdater.setProgressContext(
            artifactIndex: current,
            artifactTotal: total,
            downloadTotal: artifact.downloadCount,
          );

          // For artifacts containing multiple downloads, print the artifact name
          if (artifact.downloadCount > 1) {
            _logger.printStatus('[$current/$total] ${artifact.displayName}');
          }
        }

        try {
          await artifact.update(_artifactUpdater, _logger, _fileSystem, _osUtils, offline: offline);
        } on SocketException catch (e) {
          if (_hostsBlockedInChina.contains(e.address?.host)) {
            _logger.printError(
              'Failed to retrieve Flutter tool dependencies: ${e.message}.\n'
              "If you're in China, please see this page: "
              'https://flutter.dev/to/china-setup',
              emphasis: true,
            );
          }
          rethrow;
        }
      }
    } finally {
      _artifactUpdater.resetProgressContext();
    }
  }

  Future<bool> areRemoteArtifactsAvailable({
    String? engineVersion,
    bool includeAllPlatforms = true,
  }) async {
    final bool includeAllPlatformsState = this.includeAllPlatforms;
    var allAvailable = true;
    this.includeAllPlatforms = includeAllPlatforms;
    for (final ArtifactSet cachedArtifact in _artifacts) {
      if (cachedArtifact is EngineCachedArtifact) {
        allAvailable &= await cachedArtifact.checkForArtifacts(engineVersion);
      }
    }
    this.includeAllPlatforms = includeAllPlatformsState;
    return allAvailable;
  }

  Future<bool> doesRemoteExist(String message, Uri url) async {
    final Status status = _logger.startProgress(message);
    bool exists;
    try {
      exists = await _net.doesRemoteFileExist(url);
    } finally {
      status.stop();
    }
    return exists;
  }
}

/// Representation of a set of artifacts used by the tool.
abstract class ArtifactSet {
  ArtifactSet(this.developmentArtifact);

  /// The development artifact.
  final DevelopmentArtifact developmentArtifact;

  /// Whether the artifact is up to date.
  Future<bool> isUpToDate(FileSystem fileSystem);

  /// The environment variables (if any) required to consume the artifacts.
  Map<String, String> get environment {
    return const <String, String>{};
  }

  /// Updates the artifact.
  Future<void> update(
    ArtifactUpdater artifactUpdater,
    Logger logger,
    FileSystem fileSystem,
    OperatingSystemUtils operatingSystemUtils, {
    bool offline = false,
  });

  /// The canonical name of the artifact.
  String get name;

  /// A prettier display name.
  ///
  /// Defaults to the canonical name.
  String get displayName => name;

  /// The name of the stamp file.
  ///
  /// Defaults to the same as the artifact name.
  String get stampName => name;

  /// The number of individual downloads this artifact will perform.
  ///
  /// Defaults to 0.
  int get downloadCount => 0;
}

/// An artifact set managed by the cache.
abstract class CachedArtifact extends ArtifactSet {
  CachedArtifact(this.name, this.cache, DevelopmentArtifact developmentArtifact)
    : super(developmentArtifact);

  final Cache cache;

  @override
  final String name;

  /// The number of individual downloads this artifact will perform.
  ///
  /// Defaults to 1 for cached artifacts.
  @override
  int get downloadCount => 1;

  @override
  String get stampName => name;

  Directory get location => cache.getArtifactDirectory(name);

  String? get version => cache.getVersionFor(name);

  // Whether or not to bypass normal platform filtering for this artifact.
  bool get ignorePlatformFiltering {
    return cache.includeAllPlatforms ||
        (cache.platformOverrideArtifacts != null &&
            cache.platformOverrideArtifacts!.contains(developmentArtifact.name));
  }

  @override
  Future<bool> isUpToDate(FileSystem fileSystem) async {
    if (!location.existsSync()) {
      return false;
    }
    if (version != cache.getStampFor(stampName)) {
      return false;
    }
    return isUpToDateInner(fileSystem);
  }

  @override
  Future<void> update(
    ArtifactUpdater artifactUpdater,
    Logger logger,
    FileSystem fileSystem,
    OperatingSystemUtils operatingSystemUtils, {
    bool offline = false,
  }) async {
    if (!location.existsSync()) {
      try {
        location.createSync(recursive: true);
      } on FileSystemException catch (err) {
        logger.printError(err.toString());
        throwToolExit(
          'Failed to create directory for flutter cache at ${location.path}. '
          'Flutter may be missing permissions in its cache directory.',
        );
      }
    }
    final String? version = this.version;
    if (version == null) {
      logger.printWarning(
        'No known version for the artifact name "$name". '
        'Flutter can continue, but the artifact may be re-downloaded on '
        'subsequent invocations until the problem is resolved.',
      );
      return;
    }
    await updateInner(artifactUpdater, fileSystem, operatingSystemUtils);
    try {
      cache.setStampFor(stampName, version);
    } on FileSystemException catch (err) {
      logger.printWarning(
        'The new artifact "$name" was downloaded, but Flutter failed to update '
        'its stamp file, receiving the error "$err". '
        'Flutter can continue, but the artifact may be re-downloaded on '
        'subsequent invocations until the problem is resolved.',
      );
    }
    artifactUpdater.removeDownloadedFiles();
  }

  /// Hook method for extra checks for being up-to-date.
  bool isUpToDateInner(FileSystem fileSystem) => true;

  Future<void> updateInner(
    ArtifactUpdater artifactUpdater,
    FileSystem fileSystem,
    OperatingSystemUtils operatingSystemUtils,
  );
}

abstract class EngineCachedArtifact extends CachedArtifact {
  EngineCachedArtifact(this.stampName, Cache cache, DevelopmentArtifact developmentArtifact)
    : super('engine', cache, developmentArtifact);

  @override
  final String stampName;

  @override
  String? get version => cache.engineRevision;

  @override
  int get downloadCount => getPackageDirs().length + getBinaryDirs().length;

  /// Return a list of (directory path, download URL path) tuples.
  List<List<String>> getBinaryDirs();

  /// A list of cache directory paths to which the LICENSE file should be copied.
  List<String> getLicenseDirs();

  /// A list of the dart package directories to download.
  List<String> getPackageDirs();

  @override
  bool isUpToDateInner(FileSystem fileSystem) {
    final Directory pkgDir = cache.getCacheDir('pkg');
    for (final String pkgName in getPackageDirs()) {
      final String pkgPath = fileSystem.path.join(pkgDir.path, pkgName);
      if (!fileSystem.directory(pkgPath).existsSync()) {
        return false;
      }
    }

    for (final List<String> toolsDir in getBinaryDirs()) {
      final Directory dir = fileSystem.directory(fileSystem.path.join(location.path, toolsDir[0]));
      if (!dir.existsSync()) {
        return false;
      }
    }

    for (final String licenseDir in getLicenseDirs()) {
      final File file = fileSystem.file(fileSystem.path.join(location.path, licenseDir, 'LICENSE'));
      if (!file.existsSync()) {
        return false;
      }
    }
    return true;
  }

  @override
  Future<void> updateInner(
    ArtifactUpdater artifactUpdater,
    FileSystem fileSystem,
    OperatingSystemUtils operatingSystemUtils,
  ) async {
    final url = '${cache.storageBaseUrl}/flutter_infra_release/flutter/$version/';

    final Directory pkgDir = cache.getCacheDir('pkg');
    for (final String pkgName in getPackageDirs()) {
      await artifactUpdater.downloadZipArchive(pkgName, Uri.parse('$url$pkgName.zip'), pkgDir);
    }

    for (final List<String> toolsDir in getBinaryDirs()) {
      final String cacheDir = toolsDir[0];
      final String urlPath = toolsDir[1];
      final Directory dir = fileSystem.directory(fileSystem.path.join(location.path, cacheDir));

      final String friendlyName = urlPath.replaceAll('/artifacts.zip', '').replaceAll('.zip', '');
      await artifactUpdater.downloadZipArchive(friendlyName, Uri.parse(url + urlPath), dir);

      _makeFilesExecutable(dir, operatingSystemUtils);
    }

    final File licenseSource = cache.getLicenseFile();
    for (final String licenseDir in getLicenseDirs()) {
      final String licenseDestinationPath = fileSystem.path.join(
        location.path,
        licenseDir,
        'LICENSE',
      );
      await licenseSource.copy(licenseDestinationPath);
    }
  }

  Future<bool> checkForArtifacts(String? engineVersion) async {
    engineVersion ??= version;
    final url = '${cache.storageBaseUrl}/flutter_infra_release/flutter/$engineVersion/';

    var exists = false;
    for (final String pkgName in getPackageDirs()) {
      exists = await cache.doesRemoteExist(
        'Checking package $pkgName is available...',
        Uri.parse('$url$pkgName.zip'),
      );
      if (!exists) {
        return false;
      }
    }

    for (final List<String> toolsDir in getBinaryDirs()) {
      final String cacheDir = toolsDir[0];
      final String urlPath = toolsDir[1];
      exists = await cache.doesRemoteExist(
        'Checking $cacheDir tools are available...',
        Uri.parse(url + urlPath),
      );
      if (!exists) {
        return false;
      }
    }
    return true;
  }

  void _makeFilesExecutable(Directory dir, OperatingSystemUtils operatingSystemUtils) {
    operatingSystemUtils.chmod(dir, 'a+r,a+x');
    for (final File file in dir.listSync(recursive: true).whereType<File>()) {
      final FileStat stat = file.statSync();
      final isUserExecutable = ((stat.mode >> 6) & 0x1) == 1;
      if (file.basename == 'flutter_tester' || isUserExecutable) {
        // Make the file readable and executable by all users.
        operatingSystemUtils.chmod(file, 'a+r,a+x');
      }
    }
  }
}

/// An API for downloading and un-archiving artifacts, such as engine binaries or
/// additional source code.
class ArtifactUpdater {
  ArtifactUpdater({
    required this._operatingSystemUtils,
    required this._logger,
    required this._fileSystem,
    required this._tempStorage,
    required this._httpClient,
    required this._platform,
    required this._allowedBaseUrls,
    this._stdio,
  });

  /// The number of times the artifact updater will repeat the artifact download loop.
  static const _kRetryCount = 2;

  final Logger _logger;
  final OperatingSystemUtils _operatingSystemUtils;
  final FileSystem _fileSystem;
  final Directory _tempStorage;
  final HttpClient _httpClient;
  final Platform _platform;

  /// Artifacts should only be downloaded from URLs that use one of these
  /// prefixes.
  ///
  /// [ArtifactUpdater] will issue a warning if an attempt to download from a
  /// non-compliant URL is made.
  final List<String> _allowedBaseUrls;

  final Stdio? _stdio;

  /// Keep track of the files we've downloaded for this execution so we
  /// can delete them after completion. We don't delete them right after
  /// extraction in case [ArtifactSet.update] is interrupted, so we can
  /// restart without starting from scratch.
  @visibleForTesting
  final downloadedFiles = <File>[];

  // Progress tracking state for download output formatting.
  int _artifactIndex = 0;
  int _artifactTotal = 0;
  int _downloadIndex = 0;
  int _downloadTotal = 0;

  /// Sets the progress context for artifact downloads.
  ///
  /// This is called before each artifact update to enable progress output.
  /// The [downloadIndex] can be used to set the current download index
  /// within an artifact (1-based).
  void setProgressContext({
    required int artifactIndex,
    required int artifactTotal,
    required int downloadTotal,
    int downloadIndex = 0,
  }) {
    _artifactIndex = artifactIndex;
    _artifactTotal = artifactTotal;
    _downloadIndex = downloadIndex;
    _downloadTotal = downloadTotal;
  }

  void resetProgressContext() {
    _artifactIndex = 0;
    _artifactTotal = 0;
    _downloadIndex = 0;
    _downloadTotal = 0;
  }

  /// Creates the appropriate display for the current terminal capabilities.
  _DownloadDisplay _createDisplay(String statusMessage) {
    if (_stdio != null && _logger.supportsColor) {
      return _ProgressBarDisplay(stdio: _stdio, statusMessage: statusMessage);
    }
    return _SpinnerDisplay(logger: _logger, statusMessage: statusMessage);
  }

  /// These filenames, should they exist after extracting an archive, should be deleted.
  static const _denylistedBasenames = <String>{
    'entitlements.txt',
    'without_entitlements.txt',
    'unsigned_binaries.txt',
  };
  void _removeDenylistedFiles(Directory directory) {
    for (final FileSystemEntity entity in directory.listSync(recursive: true)) {
      if (entity is! File) {
        continue;
      }
      if (_denylistedBasenames.contains(entity.basename)) {
        entity.deleteSync();
      }
    }
  }

  /// Download a zip archive from the given [url] and unzip it to [location].
  Future<void> downloadZipArchive(String artifactName, Uri url, Directory location) {
    return _downloadArchive(artifactName, url, location, _operatingSystemUtils.unzip);
  }

  /// Download a gzipped tarball from the given [url] and unpack it to [location].
  Future<void> downloadZippedTarball(String artifactName, Uri url, Directory location) {
    return _downloadArchive(artifactName, url, location, _operatingSystemUtils.unpack);
  }

  /// Download a file from the given [url] and copy it to [location].
  Future<void> downloadFile(String artifactName, Uri url, Directory location) {
    return _downloadArchive(artifactName, url, location, (File file, Directory dir) {
      file.copySync(dir.childFile(file.basename).path);
    });
  }

  /// Formats a download message with progress context.
  @visibleForTesting
  String formatProgressMessage(String artifactName) {
    final int displayIndex = _downloadIndex + 1;
    if (_downloadTotal == 1) {
      return '[$_artifactIndex/$_artifactTotal] $artifactName';
    } else {
      final prefix = displayIndex == _downloadTotal ? '└─' : '├─';
      return '  $prefix [$displayIndex/$_downloadTotal] $artifactName';
    }
  }

  /// Download an archive from the given [url] and unzip it to [location].
  Future<void> _downloadArchive(
    String artifactName,
    Uri url,
    Directory location,
    void Function(File, Directory) extractor,
  ) async {
    final String downloadPath = flattenNameSubdirs(url, _fileSystem);
    final File tempFile = _createDownloadFile(downloadPath);
    int retries = _kRetryCount;
    final String formattedMessage = formatProgressMessage(artifactName);
    _downloadIndex++;

    while (retries > 0) {
      final _DownloadDisplay display = _createDisplay(formattedMessage);
      display.start();

      try {
        _ensureExists(tempFile.parent);
        if (tempFile.existsSync()) {
          tempFile.deleteSync();
        }
        await _download(url, tempFile, display);

        if (!tempFile.existsSync()) {
          throw Exception('Did not find downloaded file ${tempFile.path}');
        }
        display.finish();
      } on Exception catch (err) {
        display.cancel();
        _logger.printTrace(err.toString());
        retries -= 1;
        if (retries == 0) {
          throwToolExit(
            'Failed to download $url. Ensure you have network connectivity and then try again.\n$err',
          );
        }
        continue;
      } on ArgumentError catch (error) {
        display.cancel();
        final String? overrideUrl = _platform.environment[kFlutterStorageBaseUrl];
        if (overrideUrl != null && url.toString().contains(overrideUrl)) {
          _logger.printError(error.toString());
          throwToolExit(
            'The value of $kFlutterStorageBaseUrl ($overrideUrl) could not be '
            'parsed as a valid url. Please see https://flutter.dev/to/use-mirror-site '
            'for an example of how to use it.\n'
            'Full URL: $url',
            exitCode: kNetworkProblemExitCode,
          );
        }
        // This error should not be hit if there was not a storage URL override, allow the
        // tool to crash.
        rethrow;
      }

      /// Unzipping multiple file into a directory will not remove old files
      /// from previous versions that are not present in the new bundle.
      final Directory destination = location.childDirectory(
        tempFile.fileSystem.path.basenameWithoutExtension(tempFile.path),
      );
      try {
        ErrorHandlingFileSystem.deleteIfExists(destination, recursive: true);
      } on FileSystemException catch (error) {
        // Error that indicates another program has this file open and that it
        // cannot be deleted. For the cache, this is either the analyzer reading
        // the sky_engine package or a running flutter_tester device.
        const kSharingViolation = 32;
        if (_platform.isWindows && error.osError?.errorCode == kSharingViolation) {
          throwToolExit(
            'Failed to delete ${destination.path} because the local file/directory is in use '
            'by another process. Try closing any running IDEs or editors and trying '
            'again',
          );
        }
      }
      _ensureExists(location);

      try {
        extractor(tempFile, location);
      } on Exception catch (err) {
        retries -= 1;
        if (retries == 0) {
          throwToolExit(
            'Flutter could not download and/or extract $url. Ensure you have '
            'network connectivity and all of the required dependencies listed at '
            'https://flutter.dev/setup.\nThe original exception was: $err.',
          );
        }
        _deleteIgnoringErrors(tempFile);
        continue;
      }
      _removeDenylistedFiles(location);
      return;
    }
  }

  /// Download bytes from [url], throwing non-200 responses as an exception.
  ///
  /// Validates that the md5 of the content bytes matches the provided
  /// `x-goog-hash` header, if present. This header should contain an md5 hash
  /// if the download source is Google cloud storage.
  ///
  /// See also:
  ///   * https://cloud.google.com/storage/docs/xml-api/reference-headers#xgooghash
  Future<void> _download(Uri url, File file, _DownloadDisplay display) async {
    final bool isAllowedUrl = _allowedBaseUrls.any(
      (String baseUrl) => url.toString().startsWith(baseUrl),
    );

    // In tests make this a hard failure.
    assert(
      isAllowedUrl,
      'URL not allowed: $url\n'
      'Allowed URLs must be based on one of: ${_allowedBaseUrls.join(', ')}',
    );

    // In production, issue a warning but allow the download to proceed.
    if (!isAllowedUrl) {
      display.pause();
      _logger.printWarning(
        'Downloading an artifact that may not be reachable in some environments (e.g. firewalled environments): $url\n'
        'This should not have happened. This is likely a Flutter SDK bug. Please file an issue at https://github.com/flutter/flutter/issues/new?template=01_activation.yml',
      );
      display.resume();
    }

    final HttpClientRequest request = await _httpClient.getUrl(url);
    final HttpClientResponse response = await request.close();
    if (response.statusCode != HttpStatus.ok) {
      throw Exception(response.statusCode);
    }

    final String? md5Hash = _expectedMd5(response.headers);
    ByteConversionSink? inputSink;
    late StreamController<Digest> digests;
    if (md5Hash != null) {
      _logger.printTrace('Content $url md5 hash: $md5Hash');
      digests = StreamController<Digest>();
      inputSink = md5.startChunkedConversion(digests);
    }
    final int contentLength = response.contentLength;
    final RandomAccessFile randomAccessFile = file.openSync(mode: FileMode.writeOnly);
    await response.forEach((List<int> chunk) {
      inputSink?.add(chunk);
      randomAccessFile.writeFromSync(chunk);
      display.onChunk(chunk.length, contentLength);
    });
    randomAccessFile.closeSync();
    if (inputSink != null) {
      inputSink.close();
      final Digest digest = await digests.stream.last;
      final String rawDigest = base64.encode(digest.bytes);
      if (rawDigest != md5Hash) {
        throw Exception(
          'Expected $url to have md5 checksum $md5Hash, but was $rawDigest. This '
          'may indicate a problem with your connection to the Flutter backend servers. '
          'Please re-try the download after confirming that your network connection is '
          'stable.',
        );
      }
    }
  }

  String? _expectedMd5(HttpHeaders httpHeaders) {
    final List<String>? values = httpHeaders['x-goog-hash'];
    if (values == null) {
      return null;
    }
    String? rawMd5Hash;
    for (final String value in values) {
      if (value.startsWith('md5=')) {
        rawMd5Hash = value;
        break;
      }
    }
    if (rawMd5Hash == null) {
      return null;
    }
    final List<String> segments = rawMd5Hash.split('md5=');
    if (segments.length < 2) {
      return null;
    }
    final String md5Hash = segments[1];
    if (md5Hash.isEmpty) {
      return null;
    }
    return md5Hash;
  }

  /// Create a temporary file and add it to the [downloadedFiles].
  File _createDownloadFile(String name) {
    final File tempFile = _fileSystem.file(_fileSystem.path.join(_tempStorage.path, name));
    downloadedFiles.add(tempFile);
    return tempFile;
  }

  /// Create the given [directory] and parents, as necessary.
  void _ensureExists(Directory directory) {
    if (!directory.existsSync()) {
      directory.createSync(recursive: true);
    }
  }

  /// Clear any zip/gzip files downloaded.
  void removeDownloadedFiles() {
    for (final File file in downloadedFiles) {
      if (!file.existsSync()) {
        continue;
      }
      try {
        file.deleteSync();
      } on FileSystemException catch (e) {
        _logger.printWarning('Failed to delete "${file.path}". Please delete manually. $e');
        continue;
      }
      for (
        Directory directory = file.parent;
        directory.absolute.path != _tempStorage.absolute.path;
        directory = directory.parent
      ) {
        // Handle race condition when the directory is deleted before this step
        if (!directory.existsSync()) {
          break;
        }
        if (directory.listSync().isNotEmpty) {
          break;
        }
        _deleteIgnoringErrors(directory);
      }
    }
  }

  static void _deleteIgnoringErrors(FileSystemEntity entity) {
    if (!entity.existsSync()) {
      return;
    }
    try {
      entity.deleteSync();
    } on FileSystemException {
      // Ignore errors.
    }
  }
}

@visibleForTesting
String flattenNameSubdirs(Uri url, FileSystem fileSystem) {
  final pieces = <String>[url.host, ...url.pathSegments];
  final Iterable<String> convertedPieces = pieces.map<String>(_flattenNameNoSubdirs);
  return fileSystem.path.joinAll(convertedPieces);
}

/// Given a name containing slashes, colons, and backslashes, expand it into
/// something that doesn't.
String _flattenNameNoSubdirs(String fileName) {
  final replacedCodeUnits = <int>[
    for (final int codeUnit in fileName.codeUnits)
      ..._flattenNameSubstitutions[codeUnit] ?? <int>[codeUnit],
  ];
  return String.fromCharCodes(replacedCodeUnits);
}

// Many characters are problematic in filenames, especially on Windows.
final _flattenNameSubstitutions = <int, List<int>>{
  r'@'.codeUnitAt(0): '@@'.codeUnits,
  r'/'.codeUnitAt(0): '@s@'.codeUnits,
  r'\'.codeUnitAt(0): '@bs@'.codeUnits,
  r':'.codeUnitAt(0): '@c@'.codeUnits,
  r'%'.codeUnitAt(0): '@per@'.codeUnits,
  r'*'.codeUnitAt(0): '@ast@'.codeUnits,
  r'<'.codeUnitAt(0): '@lt@'.codeUnits,
  r'>'.codeUnitAt(0): '@gt@'.codeUnits,
  r'"'.codeUnitAt(0): '@q@'.codeUnits,
  r'|'.codeUnitAt(0): '@pip@'.codeUnits,
  r'?'.codeUnitAt(0): '@ques@'.codeUnits,
};

/// Abstraction for displaying download progress.
///
/// Two implementations exist:
/// - [_ProgressBarDisplay]: ANSI progress bar for terminals with color support.
/// - [_SpinnerDisplay]: Spinner-based display via [Logger.startProgress].
abstract class _DownloadDisplay {
  /// Called when the download begins.
  void start();

  /// Called when a chunk of data is received.
  void onChunk(int chunkSize, int contentLength);

  /// Called when the download completes successfully.
  void finish();

  /// Called when the download is cancelled or fails.
  void cancel();

  /// Pauses the display (e.g. when another status message needs the terminal).
  void pause();

  /// Resumes the display after a pause.
  void resume();
}

/// Displays an ANSI progress bar with speed, ETA, and percentage.
class _ProgressBarDisplay extends _DownloadDisplay {
  _ProgressBarDisplay({required this._stdio, required this.statusMessage});

  static const int _maxTerminalWidth = 80;
  static const int _progressUpdateIntervalMs = 100;

  final Stdio _stdio;
  final String statusMessage;
  final DownloadProgress _progress = DownloadProgress();
  final Stopwatch _stopwatch = Stopwatch();
  int _lastUpdateMs = 0;

  int get _terminalWidth =>
      (_stdio.terminalColumns ?? _maxTerminalWidth).clamp(0, _maxTerminalWidth);

  @override
  void start() {
    _stopwatch.start();
    _stdio.stdoutWrite('$statusMessage\n');
  }

  @override
  void onChunk(int chunkSize, int contentLength) {
    if (_progress.totalBytes < 0) {
      _progress.totalBytes = contentLength;
    }
    _progress.addBytesReceived(chunkSize);
    final int currentMs = _stopwatch.elapsedMilliseconds;
    if (currentMs >= _lastUpdateMs + _progressUpdateIntervalMs) {
      _lastUpdateMs = currentMs;
      final String line = _progress.formatProgressLine(
        elapsed: _stopwatch.elapsed,
        terminalWidth: _terminalWidth,
      );
      _stdio.stdoutWrite('${AnsiTerminal.clearAndReturnCode}$line');
    }
  }

  void _stopAndClear() {
    _stopwatch.stop();
    _stdio.stdoutWrite(
      '${AnsiTerminal.clearAndReturnCode}'
      '${AnsiTerminal.cursorUpLineCode}'
      '${AnsiTerminal.clearAndReturnCode}',
    );
  }

  @override
  void finish() {
    _stopAndClear();
    final String summary = _progress.formatCompletionSummary(_stopwatch.elapsed);
    final int padding = _terminalWidth - statusMessage.length - summary.length;
    final line = '$statusMessage${' ' * max(1, padding)}$summary';
    _stdio.stdoutWrite('$line\n');
  }

  @override
  void cancel() {
    _stopAndClear();
  }

  @override
  void pause() {}

  @override
  void resume() {}
}

/// Displays a spinner via [Logger.startProgress].
class _SpinnerDisplay extends _DownloadDisplay {
  _SpinnerDisplay({required this._logger, required this._statusMessage});

  final Logger _logger;
  final String _statusMessage;
  Status? _status;

  @override
  void start() {
    _status = _logger.startProgress(_statusMessage);
  }

  @override
  void onChunk(int chunkSize, int contentLength) {}

  @override
  void finish() {
    _status?.stop();
  }

  @override
  void cancel() {
    _status?.stop();
  }

  @override
  void pause() {
    _status?.pause();
  }

  @override
  void resume() {
    _status?.resume();
  }
}

/// Tracks download progress and provides formatted display strings.
@visibleForTesting
class DownloadProgress {
  /// Total expected bytes, or -1 if unknown.
  int totalBytes = -1;

  int _bytesReceived = 0;
  int get bytesReceived => _bytesReceived;

  void addBytesReceived(int bytes) {
    _bytesReceived += bytes;
  }

  bool get hasKnownSize => totalBytes > 0;

  double get fractionReceived => hasKnownSize ? (_bytesReceived / totalBytes).clamp(0.0, 1.0) : 0.0;

  int get percentReceived => (fractionReceived * 100).round();

  /// Download speed in bytes per second.
  double speedBytesPerSecond(Duration elapsed) {
    if (elapsed.inMilliseconds == 0) {
      return 0;
    }
    return _bytesReceived * 1000 / elapsed.inMilliseconds;
  }

  /// Estimated time remaining.
  Duration? timeRemaining(Duration elapsed) {
    final double speed = speedBytesPerSecond(elapsed);
    if (!hasKnownSize || speed == 0) {
      return null;
    }
    final int totalRemainingBytes = totalBytes - _bytesReceived;
    return Duration(milliseconds: (totalRemainingBytes * 1000 / speed).round());
  }

  static const _subBlocks = ['▏', '▎', '▍', '▌', '▋', '▊', '▉'];

  /// Renders a progress bar with sub-character precision.
  ///
  /// Uses 1/8-block characters for a smooth fill edge.
  String renderProgressBar(int width) {
    if (!hasKnownSize || width <= 0) {
      return '';
    }
    final int totalEighths = (fractionReceived * width * 8).round();
    final int fullBlocks = totalEighths ~/ 8;
    final int remainder = totalEighths % 8;
    final int emptyBlocks = width - fullBlocks - 1;
    final String filled = '█' * fullBlocks;
    final String partial = remainder > 0 ? _subBlocks[remainder - 1] : ' ';
    final String empty = ' ' * emptyBlocks;
    return '$filled$partial$empty';
  }

  /// Formats download speed as a human-readable string.
  String formatSpeed(Duration elapsed) {
    return '${getSizeAsPlatformMB(speedBytesPerSecond(elapsed).round())}/s';
  }

  /// Formats bytes received and total.
  String formatBytes() {
    if (hasKnownSize) {
      return '${getSizeAsPlatformMB(_bytesReceived)}'
          '/${getSizeAsPlatformMB(totalBytes)}';
    }
    return getSizeAsPlatformMB(_bytesReceived);
  }

  /// Formats estimated time remaining.
  String formatRemaining(Duration elapsed) {
    final Duration? rem = timeRemaining(elapsed);
    if (rem == null) {
      return '';
    }
    return 'ETA ${getElapsedAsSeconds(rem)}';
  }

  /// Formats the full progress line for terminal display.
  String formatProgressLine({required Duration elapsed, required int terminalWidth}) {
    final String indent = ' ' * 5;
    final percentReceivedStr = hasKnownSize ? '${percentReceived.toString().padLeft(3)}%' : '';
    final String bytesStr = formatBytes();
    final String speedStr = formatSpeed(elapsed);
    final String etaStr = formatRemaining(elapsed);

    final parts = <String>[percentReceivedStr, bytesStr, speedStr, etaStr];
    final String info = parts.where((String s) => s.isNotEmpty).join('  ');

    // The progress bar is 28 characters wide and terminated on either side by
    // thin vertical lines which take up another 2 characters. 28 characters was
    // chosen empirically to make the progress bar take up enough space to look
    // good while leaving enough space for the detailed info under "normal"
    // conditions (artifact size <1GB, download speed >1MB/s).
    const barInner = 28;
    const int barTotal = barInner + 2; // ▕ + bar + ▏
    final String line;

    // Only show the progress bar if we have enough room to show it along with
    // the info, otherwise just show the info right-aligned.
    if (hasKnownSize && terminalWidth >= indent.length + barTotal + info.length) {
      final String bar = renderProgressBar(barInner);
      final int padding = terminalWidth - indent.length - barTotal - info.length;
      line = '$indent▕$bar▏${' ' * padding}$info';
    } else {
      final int padding = terminalWidth - indent.length - info.length;
      final unclipped = '$indent${' ' * max(0, padding)}$info';
      line = unclipped.length <= terminalWidth ? unclipped : unclipped.substring(0, terminalWidth);
    }
    return line;
  }

  /// Formats the completion summary like `(21.1MB in 5.0s)`.
  String formatCompletionSummary(Duration elapsed) {
    final String size = getSizeAsPlatformMB(_bytesReceived);
    final String time = getElapsedAsSeconds(elapsed);
    return '($size in $time)';
  }
}
