// 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.

import 'package:meta/meta.dart';

import 'base/common.dart';
import 'base/file_system.dart';
import 'base/logger.dart';
import 'base/platform.dart';
import 'base/process.dart';
import 'base/time.dart';
import 'base/utils.dart';
import 'cache.dart';
import 'convert.dart';
import 'features.dart';
import 'git.dart';
import 'globals.dart' as globals;

/// The default version when a version could not be determined.
const kUnknownFrameworkVersion = '0.0.0-unknown';

/// A git shortcut for the branch that is being tracked by the current one.
///
/// See `man gitrevisions` for more information.
const kGitTrackingUpstream = '@{upstream}';

/// Replacement name when the branch is user-specific.
const kUserBranch = '[user-branch]';

/// This maps old branch names to the names of branches that replaced them.
///
/// For example, in 2021 we deprecated the "dev" channel and transitioned "dev"
/// users to the "beta" channel.
const kObsoleteBranches = <String, String>{'dev': 'beta'};

/// The names of each channel/branch in order of increasing stability.
enum Channel { master, main, beta, stable }

// Beware: Keep order in accordance with stability
const kOfficialChannels = <String>{'master', 'main', 'beta', 'stable'};

const kChannelDescriptions = <String, String>{
  'master': 'latest development branch, for contributors',
  'main': 'latest development branch, follows master channel',
  'beta': 'updated monthly, recommended for experienced users',
  'stable': 'updated quarterly, for new users and for production app releases',
};

const kDevelopmentChannels = <String>{'master', 'main'};

/// Retrieve a human-readable name for a given [channel].
///
/// Requires [kOfficialChannels] to be correctly ordered.
String getNameForChannel(Channel channel) {
  return kOfficialChannels.elementAt(channel.index);
}

/// Retrieve the [Channel] representation for a string [name].
///
/// Returns `null` if [name] is not in the list of official channels, according
/// to [kOfficialChannels].
Channel? getChannelForName(String name) {
  if (kOfficialChannels.contains(name)) {
    return Channel.values[kOfficialChannels.toList().indexOf(name)];
  }
  return null;
}

abstract class FlutterVersion {
  /// Parses the Flutter version from currently available tags in the local
  /// repo.
  factory FlutterVersion({
    SystemClock clock = const SystemClock(),
    required FileSystem fs,
    required Git git,
    required String flutterRoot,
    @protected bool fetchTags = false,
  }) {
    final File versionFile = getVersionFile(fs, flutterRoot);

    if (!fetchTags && versionFile.existsSync()) {
      final _FlutterVersionFromFile? version = _FlutterVersionFromFile.tryParseFromFile(
        versionFile,
        git: git,
        flutterRoot: flutterRoot,
      );
      if (version != null) {
        return version;
      }
    }

    // if we are fetching tags, ignore cached versionFile
    if (fetchTags && versionFile.existsSync()) {
      versionFile.deleteSync();
      final File legacyVersionFile = fs.file(fs.path.join(flutterRoot, 'version'));
      if (legacyVersionFile.existsSync()) {
        legacyVersionFile.deleteSync();
      }
    }

    final String frameworkRevision = git
        .logSync(['-n', '1', '--pretty=format:%H'], workingDirectory: flutterRoot)
        .stdout
        .trim();

    return FlutterVersion.fromRevision(
      clock: clock,
      frameworkRevision: frameworkRevision,
      fs: fs,
      flutterRoot: flutterRoot,
      fetchTags: fetchTags,
      git: git,
    );
  }

  FlutterVersion._({
    required SystemClock clock,
    required Git git,
    required this.flutterRoot,
    required this.fs,
  }) : _clock = clock,
       _git = git;

  factory FlutterVersion.fromRevision({
    SystemClock clock = const SystemClock(),
    required String flutterRoot,
    required String frameworkRevision,
    required FileSystem fs,
    required Git git,
    bool fetchTags = false,
  }) {
    final GitTagVersion gitTagVersion = GitTagVersion.determine(
      globals.platform,
      git: globals.git,
      gitRef: frameworkRevision,
      workingDirectory: flutterRoot,
      fetchTags: fetchTags,
    );
    final String frameworkVersion = gitTagVersion.frameworkVersionFor(frameworkRevision);
    final result = _FlutterVersionGit._(
      clock: clock,
      flutterRoot: flutterRoot,
      frameworkRevision: frameworkRevision,
      frameworkVersion: frameworkVersion,
      gitTagVersion: gitTagVersion,
      fs: fs,
      git: git,
    );
    if (fetchTags) {
      result.ensureVersionFile();
    }
    return result;
  }

  /// Ensure the latest git tags are fetched and recalculate [FlutterVersion].
  ///
  /// This is only required when not on beta or stable and we need to calculate
  /// the current version relative to upstream tags.
  ///
  /// This is a method and not a factory constructor so that test classes can
  /// override it.
  FlutterVersion fetchTagsAndGetVersion({SystemClock clock = const SystemClock()}) {
    // We don't need to fetch tags on beta and stable to calculate the version,
    // we should already exactly be on a tag that was pushed when this release
    // was published.
    if (channel != 'master' && channel != 'main') {
      return this;
    }
    return FlutterVersion(
      clock: clock,
      flutterRoot: flutterRoot,
      fs: fs,
      fetchTags: true,
      git: _git,
    );
  }

  final FileSystem fs;
  final Git _git;
  final SystemClock _clock;

  String? get repositoryUrl;

  GitTagVersion get gitTagVersion;

  /// The channel is the upstream branch.
  ///
  /// `master`, `dev`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, ...
  String get channel;

  /// The SHA describing the commit being used for the SDK and tools provide in `flutter/flutter`.
  ///
  /// The _exception_ is the _engine artifacts_, which are downloaded separately as [engineRevision].
  String get frameworkRevision;

  /// The shorter Git commit SHA of [frameworkRevision].
  String get frameworkRevisionShort => _shortGitRevision(frameworkRevision);
  String get frameworkVersion;

  String get devToolsVersion;
  String get dartSdkVersion;

  /// The SHA describing the commit being used for the engine artifacts, which are compiled from the `engine/` sub-directory.
  ///
  /// When using a standard release build, or master channel, [engineRevision] will be identical to [frameworkRevision] since
  /// the monorepository merge (as of 2025); however when modifying the framework (or engine) locally, or using a flag such
  /// as `FLUTTER_PREBUILT_ENGINE_VERSION=...`, the engine SHA will be _different_ than the [frameworkRevision].
  String get engineRevision;

  /// The hash produced by the source code responsible for engine artifacts being built.
  String? get engineContentHash;

  /// The shorter Git commit SHA of [engineRevision].
  String get engineRevisionShort => _shortGitRevision(engineRevision);

  // This is static as it is called from a constructor.
  static File getVersionFile(FileSystem fs, String flutterRoot) {
    return fs.file(fs.path.join(flutterRoot, 'bin', 'cache', 'flutter.version.json'));
  }

  final String flutterRoot;

  String _getTimeSinceCommit({String? revision}) {
    return _git
        .logSync(['-n', '1', '--pretty=format:%ar', ?revision], workingDirectory: flutterRoot)
        .stdout
        .trim();
  }

  // TODO(fujino): calculate this relative to frameworkCommitDate for
  // _FlutterVersionFromFile so we don't need a git call.
  late final String frameworkAge = _getTimeSinceCommit();
  late final String engineAge = engineBuildDate != null
      ? _clock.now().difference(DateTime.parse(engineBuildDate!)).ago()
      : _getTimeSinceCommit(revision: engineRevision);

  /// Populates bin/cache/flutter.version.json with the current version information, if it does not
  /// already exist.
  void ensureVersionFile();

  /// Deletes bin/cache/flutter.version.json so it can be regenerated on the next invocation of the
  /// tool.
  void deleteVersionFile() {
    final File versionFile = getVersionFile(fs, flutterRoot);
    if (versionFile.existsSync()) {
      versionFile.deleteSync();
    }
  }

  @override
  String toString() {
    final versionText = frameworkVersion == kUnknownFrameworkVersion ? '' : ' $frameworkVersion';
    final flutterText =
        'Flutter$versionText • channel $channel • ${repositoryUrl ?? 'unknown source'}';
    final frameworkText =
        'Framework • revision $frameworkRevisionShort ($frameworkAge) • $frameworkCommitDate';
    String engineText;
    if (engineContentHash != null) {
      engineText = 'Engine • hash $engineContentHash (revision $engineRevisionShort) ($engineAge)';
    } else {
      engineText = 'Engine • revision $engineRevisionShort ($engineAge)';
    }
    if (engineCommitDate != null) {
      engineText = '$engineText • $engineCommitDate';
    }

    final toolsText = 'Tools • Dart $dartSdkVersion • DevTools $devToolsVersion';

    // Flutter 1.10.2-pre.69 • channel master • https://github.com/flutter/flutter.git
    // Framework • revision 340c158f32 (85 minutes ago) • 2018-10-26 11:27:22 -0400
    // Engine • revision 9c46333e14 (96 minutes ago) • 2018-10-26 11:16:22 -0400
    // Tools • Dart 2.1.0 (build 2.1.0-dev.8.0 bf26f760b1)

    return '$flutterText\n$frameworkText\n$engineText\n$toolsText';
  }

  Map<String, Object> toJson() => <String, Object>{
    'frameworkVersion': frameworkVersion,
    'channel': channel,
    'repositoryUrl': repositoryUrl ?? 'unknown source',
    'frameworkRevision': frameworkRevision,
    'frameworkCommitDate': frameworkCommitDate,
    'engineRevision': engineRevision,
    'engineCommitDate': ?engineCommitDate,
    'engineContentHash': ?engineContentHash,
    'engineBuildDate': ?engineBuildDate,
    'dartSdkVersion': dartSdkVersion,
    'devToolsVersion': devToolsVersion,
    'flutterVersion': frameworkVersion,
  };

  /// A date String describing the [frameworkRevision] commit.
  ///
  /// If a git command fails, this will return a placeholder date.
  String get frameworkCommitDate;

  /// A date String describing the [engineRevision] commit.
  ///
  /// If a git command fails, this will return a placeholder date.
  ///
  /// If no date was recorded ([engineCommitDate] is a newly stored field),
  /// the date is omitted, and left `null`.
  String? get engineCommitDate;

  /// A date String describing the [engineRevision] build time.
  ///
  /// If no date was recorded ([engineCommitDate] is a newly stored field),
  /// the date is omitted, and left `null`.
  String? get engineBuildDate;

  /// Checks if the currently installed version of Flutter is up-to-date, and
  /// warns the user if it isn't.
  ///
  /// This function must run while [Cache.lock] is acquired because it reads and
  /// writes shared cache files.
  Future<void> checkFlutterVersionFreshness() async {
    // Don't perform update checks if we're not on an official channel.
    if (!kOfficialChannels.contains(channel)) {
      return;
    }
    // Don't perform the update check if the tracking remote is not standard.
    if (VersionUpstreamValidator(version: this, platform: globals.platform).run() != null) {
      return;
    }
    DateTime localFrameworkCommitDate;
    try {
      // Don't perform the update check if fetching the latest local commit failed.
      localFrameworkCommitDate = DateTime.parse(
        _gitCommitDate(git: _git, workingDirectory: flutterRoot),
      );
    } on VersionCheckError {
      return;
    } on FormatException {
      return;
    }
    final DateTime? latestFlutterCommitDate = await _getLatestAvailableFlutterDate();

    return VersionFreshnessValidator(
      version: this,
      clock: _clock,
      localFrameworkCommitDate: localFrameworkCommitDate,
      latestFlutterCommitDate: latestFlutterCommitDate,
      logger: globals.logger,
      cache: globals.cache,
      pauseTime: VersionFreshnessValidator.timeToPauseToLetUserReadTheMessage,
    ).run();
  }

  /// Gets the release date of the latest available Flutter version.
  ///
  /// This method sends a server request if it's been more than
  /// [VersionFreshnessValidator.checkAgeConsideredUpToDate] since
  /// the last version check.
  ///
  /// Returns `null` if the cached version is out-of-date or missing, and we are
  /// unable to reach the server to get the latest version.
  Future<DateTime?> _getLatestAvailableFlutterDate() async {
    globals.cache.checkLockAcquired();
    final VersionCheckStamp versionCheckStamp = await VersionCheckStamp.load(
      globals.cache,
      globals.logger,
    );

    final DateTime now = _clock.now();
    if (versionCheckStamp.lastTimeVersionWasChecked != null) {
      final Duration timeSinceLastCheck = now.difference(
        versionCheckStamp.lastTimeVersionWasChecked!,
      );

      // Don't ping the server too often. Return cached value if it's fresh.
      if (timeSinceLastCheck < VersionFreshnessValidator.checkAgeConsideredUpToDate) {
        return versionCheckStamp.lastKnownRemoteVersion;
      }
    }

    // Cache is empty or it's been a while since the last server ping. Ping the server.
    try {
      final DateTime remoteFrameworkCommitDate = DateTime.parse(
        await _fetchRemoteFrameworkCommitDate(),
      );
      await versionCheckStamp.store(
        newTimeVersionWasChecked: now,
        newKnownRemoteVersion: remoteFrameworkCommitDate,
      );
      return remoteFrameworkCommitDate;
    } on VersionCheckError catch (error) {
      // This happens when any of the git commands fails, which can happen when
      // there's no Internet connectivity. Remote version check is best effort
      // only. We do not prevent the command from running when it fails.
      globals.printTrace('Failed to check Flutter version in the remote repository: $error');
      // Still update the timestamp to avoid us hitting the server on every single
      // command if for some reason we cannot connect (eg. we may be offline).
      await versionCheckStamp.store(newTimeVersionWasChecked: now);
      return null;
    }
  }

  /// The date of the latest framework commit in the remote repository.
  ///
  /// Throws [VersionCheckError] if a git command fails, for example, when the
  /// remote git repository is not reachable due to a network issue.
  Future<String> _fetchRemoteFrameworkCommitDate() async {
    try {
      // Fetch upstream branch's commit and tags
      await _run(_git, ['fetch', '--tags']);
      return _gitCommitDate(
        git: _git,
        gitRef: kGitTrackingUpstream,
        workingDirectory: Cache.flutterRoot,
      );
    } on VersionCheckError catch (error) {
      globals.printError(error.message);
      rethrow;
    }
  }

  /// Return a short string for the version (e.g. `master/0.0.59-pre.92`, `scroll_refactor/a76bc8e22b`).
  String getVersionString({bool redactUnknownBranches = false}) {
    if (frameworkVersion != kUnknownFrameworkVersion) {
      return '${getBranchName(redactUnknownBranches: redactUnknownBranches)}/$frameworkVersion';
    }
    return '${getBranchName(redactUnknownBranches: redactUnknownBranches)}/$frameworkRevisionShort';
  }

  /// The name of the local branch.
  ///
  /// Use getBranchName() to read this.
  String? _branch;

  /// Return the branch name.
  ///
  /// If [redactUnknownBranches] is true and the branch is unknown,
  /// the branch name will be returned as `'[user-branch]'` ([kUserBranch]).
  String getBranchName({bool redactUnknownBranches = false}) {
    _branch ??= () {
      final String branch = _git
          .runSync(['symbolic-ref', '--short', 'HEAD'], workingDirectory: flutterRoot)
          .stdout
          .trim();
      return branch == 'HEAD' ? '' : branch;
    }();
    if (redactUnknownBranches || _branch!.isEmpty) {
      // Only return the branch names we know about; arbitrary branch names might contain PII.
      if (!kOfficialChannels.contains(_branch) && !kObsoleteBranches.containsKey(_branch)) {
        return kUserBranch;
      }
    }
    return _branch!;
  }

  /// Reset the version freshness information by removing the stamp file.
  ///
  /// New version freshness information will be regenerated when
  /// [checkFlutterVersionFreshness] is called after this. This is typically
  /// used when switching channels so that stale information from another
  /// channel doesn't linger.
  static Future<void> resetFlutterVersionFreshnessCheck() async {
    try {
      await globals.cache.getStampFileFor(VersionCheckStamp.flutterVersionCheckStampFile).delete();
    } on FileSystemException {
      // Ignore, since we don't mind if the file didn't exist in the first place.
    }
  }
}

// The date of the given commit hash as [gitRef]. If no hash is specified,
// then it is the HEAD of the current local branch.
//
// If lenient is true, and the git command fails, a placeholder date is
// returned. Otherwise, the VersionCheckError exception is propagated.
String _gitCommitDate({
  String gitRef = 'HEAD',
  bool lenient = false,
  required Git git,
  required String? workingDirectory,
}) {
  final RunResult result = git.logSync([
    gitRef,
    '-n',
    '1',
    '--pretty=format:%ad',
    '--date=iso',
  ], workingDirectory: workingDirectory);
  if (result.exitCode == 0) {
    return result.stdout.trim();
  }
  final error = VersionCheckError(
    'Command exited with code ${result.exitCode}: ${result.command.join(' ')}\n'
    'Standard out: ${result.stdout}\n'
    'Standard error: ${result.stderr}',
  );
  if (lenient) {
    final dummyDate = DateTime.fromMillisecondsSinceEpoch(0);
    globals.printError(
      'Failed to find the latest git commit date: $error\n'
      'Returning $dummyDate instead.',
    );
    // Return something that DateTime.parse() can parse.
    return dummyDate.toString();
  }
  throw error;
}

class _FlutterVersionFromFile extends FlutterVersion {
  _FlutterVersionFromFile._({
    required super.clock,
    required this.frameworkVersion,
    required this.channel,
    required this.repositoryUrl,
    required this.frameworkRevision,
    required this.frameworkCommitDate,
    required this.engineRevision,
    required this.engineCommitDate,
    required this.dartSdkVersion,
    required this.devToolsVersion,
    required this.gitTagVersion,
    required this.engineContentHash,
    required this.engineBuildDate,
    required super.flutterRoot,
    required super.fs,
    required super.git,
  }) : super._();

  static _FlutterVersionFromFile? tryParseFromFile(
    File jsonFile, {
    required String flutterRoot,
    required Git git,
    SystemClock clock = const SystemClock(),
  }) {
    try {
      final String jsonContents = jsonFile.readAsStringSync();
      final manifest = jsonDecode(jsonContents) as Map<String, Object?>;

      return _FlutterVersionFromFile._(
        clock: clock,
        git: git,
        frameworkVersion: manifest['frameworkVersion']! as String,
        channel: manifest['channel']! as String,
        repositoryUrl: manifest['repositoryUrl']! as String,
        frameworkRevision: manifest['frameworkRevision']! as String,
        frameworkCommitDate: manifest['frameworkCommitDate']! as String,
        engineRevision: manifest['engineRevision']! as String,
        engineCommitDate: manifest['engineCommitDate'] as String?,
        engineContentHash: manifest['engineContentHash'] as String?,
        engineBuildDate: manifest['engineBuildDate'] as String?,
        dartSdkVersion: manifest['dartSdkVersion']! as String,
        devToolsVersion: manifest['devToolsVersion']! as String,
        gitTagVersion: GitTagVersion.parse(manifest['flutterVersion']! as String),
        flutterRoot: flutterRoot,
        fs: jsonFile.fileSystem,
      );
      // ignore: avoid_catches_without_on_clauses
    } catch (err) {
      globals.printTrace('Failed to parse ${jsonFile.path} with $err');
      try {
        jsonFile.deleteSync();
      } on FileSystemException {
        globals.printTrace('Failed to delete ${jsonFile.path}');
      }
      // Returning null means fallback to git implementation.
      return null;
    }
  }

  @override
  final GitTagVersion gitTagVersion;

  @override
  final String frameworkVersion;

  @override
  final String channel;

  @override
  String getBranchName({bool redactUnknownBranches = false}) => channel;

  @override
  final String repositoryUrl;

  @override
  final String frameworkRevision;

  @override
  final String frameworkCommitDate;

  @override
  final String? engineCommitDate;

  @override
  final String? engineBuildDate;

  @override
  final String engineRevision;

  @override
  final String? engineContentHash;

  @override
  final String dartSdkVersion;

  @override
  final String devToolsVersion;

  @override
  void ensureVersionFile() {
    _ensureLegacyVersionFile(fs: fs, flutterRoot: flutterRoot, frameworkVersion: frameworkVersion);
  }
}

class _FlutterVersionGit extends FlutterVersion {
  _FlutterVersionGit._({
    required super.clock,
    required super.flutterRoot,
    required this.frameworkRevision,
    required this.frameworkVersion,
    required this.gitTagVersion,
    required super.fs,
    required super.git,
  }) : super._();

  late final FlutterEngineStampFromFile? _engineStamp = FlutterEngineStampFromFile.tryParseFromFile(
    fs.file(fs.path.join(flutterRoot, 'bin', 'cache', 'engine_stamp.json')),
  );

  @override
  final GitTagVersion gitTagVersion;

  @override
  final String frameworkRevision;

  @override
  String get frameworkCommitDate =>
      _gitCommitDate(git: _git, lenient: true, workingDirectory: flutterRoot);

  // This uses 'late final' instead of 'String get' because unlike frameworkCommitDate, it is
  // operating based on a 'gitRef: ...', which we can assume to be immutable in the context of
  // this invocation (possibly HEAD could change, but gitRef should not).
  @override
  late final String engineCommitDate =
      _engineStamp?.gitRevisionDate.toString() ??
      _gitCommitDate(
        git: _git,
        gitRef: engineRevision,
        lenient: true,
        workingDirectory: flutterRoot,
      );

  String? _repositoryUrl;
  @override
  String? get repositoryUrl {
    if (_repositoryUrl == null) {
      final String gitChannel = _git
          .runSync([
            'rev-parse',
            '--abbrev-ref',
            '--symbolic',
            kGitTrackingUpstream,
          ], workingDirectory: flutterRoot)
          .stdout
          .trim();
      final int slash = gitChannel.indexOf('/');
      if (slash != -1) {
        final String remote = gitChannel.substring(0, slash);
        _repositoryUrl = _git
            .runSync(['ls-remote', '--get-url', remote], workingDirectory: flutterRoot)
            .stdout
            .trim();
      }
    }
    return _repositoryUrl;
  }

  @override
  String get devToolsVersion => globals.cache.devToolsVersion;

  @override
  String get dartSdkVersion => globals.cache.dartSdkVersion;

  @override
  String get engineRevision => _engineStamp?.gitRevision ?? globals.cache.engineRevision;

  @override
  final String frameworkVersion;

  /// The channel is the current branch if we recognize it, or "[user-branch]" (kUserBranch).
  /// `master`, `beta`, `stable`; or old ones, like `alpha`, `hackathon`, `dev`, ...
  @override
  String get channel {
    final String channel = getBranchName(redactUnknownBranches: true);
    assert(
      kOfficialChannels.contains(channel) ||
          kObsoleteBranches.containsKey(channel) ||
          channel == kUserBranch,
      'Potential PII leak in channel name: "$channel"',
    );
    return channel;
  }

  @override
  void ensureVersionFile() {
    _ensureLegacyVersionFile(fs: fs, flutterRoot: flutterRoot, frameworkVersion: frameworkVersion);
    const encoder = JsonEncoder.withIndent('  ');
    final File newVersionFile = FlutterVersion.getVersionFile(fs, flutterRoot);
    if (!newVersionFile.existsSync()) {
      newVersionFile.writeAsStringSync(encoder.convert(toJson()));
    }
  }

  @override
  String? get engineBuildDate => _engineStamp?.buildDate.toString();

  @override
  String? get engineContentHash => _engineStamp?.contentHash;
}

void _ensureLegacyVersionFile({
  required FileSystem fs,
  required String flutterRoot,
  required String frameworkVersion,
}) {
  // TODO(matanlurey): https://github.com/flutter/flutter/issues/171900.
  if (featureFlags.isOmitLegacyVersionFileEnabled) {
    return;
  }
  final File legacyVersionFile = fs.file(fs.path.join(flutterRoot, 'version'));
  if (!legacyVersionFile.existsSync()) {
    legacyVersionFile.writeAsStringSync(frameworkVersion);
  }
}

/// Checks if the provided [version] is tracking a standard remote.
///
/// A "standard remote" is one having the same url as(in order of precedence):
///  * The value of `FLUTTER_GIT_URL` environment variable.
///  * The HTTPS or SSH url of the Flutter repository as provided by GitHub.
///
/// To initiate the validation check, call [run].
///
/// This prevents the tool to check for version freshness from the standard
/// remote but fetch updates from the upstream of current branch/channel, both
/// of which can be different.
///
/// This also prevents unnecessary freshness check from a forked repo unless the
/// user explicitly configures the environment to do so.
class VersionUpstreamValidator {
  VersionUpstreamValidator({required this.version, required this.platform});

  final Platform platform;
  final FlutterVersion version;

  /// Performs the validation against the tracking remote of the [version].
  ///
  /// Returns [VersionCheckError] if the tracking remote is not standard.
  VersionCheckError? run() {
    final String? flutterGit = platform.environment['FLUTTER_GIT_URL'];
    final String? repositoryUrl = version.repositoryUrl;

    if (repositoryUrl == null) {
      return VersionCheckError(
        'The tool could not determine the remote upstream which is being '
        'tracked by the SDK.',
      );
    }

    // Strip `.git` suffix before comparing the remotes
    final List<String> sanitizedStandardRemotes = [
      // If `FLUTTER_GIT_URL` is set, use that as standard remote.
      if (flutterGit != null)
        flutterGit
      // Else use the predefined standard remotes.
      else
        ..._standardRemotes,
    ].map((String remote) => stripDotGit(remote)).toList();

    final String sanitizedRepositoryUrl = stripDotGit(repositoryUrl);

    if (!sanitizedStandardRemotes.contains(sanitizedRepositoryUrl)) {
      if (flutterGit != null) {
        // If `FLUTTER_GIT_URL` is set, inform to either remove the
        // `FLUTTER_GIT_URL` environment variable or set it to the current
        // tracking remote.
        return VersionCheckError(
          'The Flutter SDK is tracking "$repositoryUrl" but "FLUTTER_GIT_URL" '
          'is set to "$flutterGit".\n'
          'Either remove "FLUTTER_GIT_URL" from the environment or set it to '
          '"$repositoryUrl". '
          'If this is intentional, it is recommended to use "git" directly to '
          'manage the SDK.',
        );
      }
      // If `FLUTTER_GIT_URL` is unset, inform to set the environment variable.
      return VersionCheckError(
        'The Flutter SDK is tracking a non-standard remote "$repositoryUrl".\n'
        'Set the environment variable "FLUTTER_GIT_URL" to '
        '"$repositoryUrl". '
        'If this is intentional, it is recommended to use "git" directly to '
        'manage the SDK.',
      );
    }
    return null;
  }

  // The predefined list of remotes that are considered to be standard.
  static final _standardRemotes = [
    'https://github.com/flutter/flutter.git',
    'git@github.com:flutter/flutter.git',
    'ssh://git@github.com/flutter/flutter.git',
  ];

  // Strips ".git" suffix from a given string, preferably an url.
  // For example, changes 'https://github.com/flutter/flutter.git' to 'https://github.com/flutter/flutter'.
  // URLs without ".git" suffix will remain unaffected.
  static final _patternUrlDotGit = RegExp(r'(.*)(\.git)$');
  static String stripDotGit(String url) {
    return _patternUrlDotGit.firstMatch(url)?.group(1)! ?? url;
  }
}

/// Contains data and load/save logic pertaining to Flutter version checks.
@visibleForTesting
class VersionCheckStamp {
  const VersionCheckStamp({
    this.lastTimeVersionWasChecked,
    this.lastKnownRemoteVersion,
    this.lastTimeWarningWasPrinted,
  });

  final DateTime? lastTimeVersionWasChecked;
  final DateTime? lastKnownRemoteVersion;
  final DateTime? lastTimeWarningWasPrinted;

  /// The prefix of the stamp file where we cache Flutter version check data.
  @visibleForTesting
  static const flutterVersionCheckStampFile = 'flutter_version_check';

  static Future<VersionCheckStamp> load(Cache cache, Logger logger) async {
    final String? versionCheckStamp = cache.getStampFor(flutterVersionCheckStampFile);

    if (versionCheckStamp != null) {
      // Attempt to parse stamp JSON.
      try {
        final dynamic jsonObject = json.decode(versionCheckStamp);
        if (jsonObject is Map<String, dynamic>) {
          return fromJson(jsonObject);
        } else {
          logger.printTrace('Warning: expected version stamp to be a Map but found: $jsonObject');
        }
      } on Exception catch (error, stackTrace) {
        // Do not crash if JSON is malformed.
        logger.printTrace('${error.runtimeType}: $error\n$stackTrace');
      }
    }

    // Stamp is missing or is malformed.
    return const VersionCheckStamp();
  }

  static VersionCheckStamp fromJson(Map<String, dynamic> jsonObject) {
    DateTime? readDateTime(String property) {
      return jsonObject.containsKey(property)
          ? DateTime.parse(jsonObject[property] as String)
          : null;
    }

    return VersionCheckStamp(
      lastTimeVersionWasChecked: readDateTime('lastTimeVersionWasChecked'),
      lastKnownRemoteVersion: readDateTime('lastKnownRemoteVersion'),
      lastTimeWarningWasPrinted: readDateTime('lastTimeWarningWasPrinted'),
    );
  }

  Future<void> store({
    DateTime? newTimeVersionWasChecked,
    DateTime? newKnownRemoteVersion,
    DateTime? newTimeWarningWasPrinted,
    Cache? cache,
  }) async {
    final Map<String, String> jsonData = toJson();

    if (newTimeVersionWasChecked != null) {
      jsonData['lastTimeVersionWasChecked'] = '$newTimeVersionWasChecked';
    }

    if (newKnownRemoteVersion != null) {
      jsonData['lastKnownRemoteVersion'] = '$newKnownRemoteVersion';
    }

    if (newTimeWarningWasPrinted != null) {
      jsonData['lastTimeWarningWasPrinted'] = '$newTimeWarningWasPrinted';
    }

    const prettyJsonEncoder = JsonEncoder.withIndent('  ');
    (cache ?? globals.cache).setStampFor(
      flutterVersionCheckStampFile,
      prettyJsonEncoder.convert(jsonData),
    );
  }

  Map<String, String> toJson({
    DateTime? updateTimeVersionWasChecked,
    DateTime? updateKnownRemoteVersion,
    DateTime? updateTimeWarningWasPrinted,
  }) {
    updateTimeVersionWasChecked = updateTimeVersionWasChecked ?? lastTimeVersionWasChecked;
    updateKnownRemoteVersion = updateKnownRemoteVersion ?? lastKnownRemoteVersion;
    updateTimeWarningWasPrinted = updateTimeWarningWasPrinted ?? lastTimeWarningWasPrinted;

    final jsonData = <String, String>{};

    if (updateTimeVersionWasChecked != null) {
      jsonData['lastTimeVersionWasChecked'] = '$updateTimeVersionWasChecked';
    }

    if (updateKnownRemoteVersion != null) {
      jsonData['lastKnownRemoteVersion'] = '$updateKnownRemoteVersion';
    }

    if (updateTimeWarningWasPrinted != null) {
      jsonData['lastTimeWarningWasPrinted'] = '$updateTimeWarningWasPrinted';
    }

    return jsonData;
  }
}

/// Thrown when we fail to check Flutter version.
///
/// This can happen when we attempt to `git fetch` but there is no network, or
/// when the installation is not git-based (e.g. a user clones the repo but
/// then removes .git).
class VersionCheckError implements Exception {
  VersionCheckError(this.message);

  final String message;

  @override
  String toString() => '$VersionCheckError: $message';
}

/// Runs [command] in the root of the Flutter installation and returns the
/// standard output as a string.
///
/// If the command fails, throws a [ToolExit] exception.
Future<String> _run(Git git, List<String> command) async {
  // TODO(matanlurey): Inline this in the single place it's called in this file.
  final RunResult results = await git.run(command, workingDirectory: Cache.flutterRoot);

  if (results.exitCode == 0) {
    return results.stdout.trim();
  }

  throw VersionCheckError(
    'Command exited with code ${results.exitCode}: ${command.join(' ')}\n'
    'Standard error: ${results.stderr}',
  );
}

String _shortGitRevision(String? revision) {
  if (revision == null) {
    return '';
  }
  return revision.length > 10 ? revision.substring(0, 10) : revision;
}

/// Version of Flutter SDK parsed from Git.
class GitTagVersion {
  const GitTagVersion({
    required this.x,
    required this.y,
    required this.z,
    required this.hash,
    required this.gitTag,
    this.hotfix,
    this.devVersion,
    this.devPatch,
    this.commits,
  });
  const GitTagVersion.unknown()
    : x = null,
      y = null,
      z = null,
      hotfix = null,
      commits = 0,
      devVersion = null,
      devPatch = null,
      hash = '',
      gitTag = '';

  /// The X in vX.Y.Z.
  final int? x;

  /// The Y in vX.Y.Z.
  final int? y;

  /// The Z in vX.Y.Z.
  final int? z;

  /// the F in vX.Y.Z+hotfix.F.
  final int? hotfix;

  /// Number of commits since the vX.Y.Z tag.
  final int? commits;

  /// The git hash (or an abbreviation thereof) for this commit.
  final String hash;

  /// The N in X.Y.Z-dev.N.M.
  final int? devVersion;

  /// The M in X.Y.Z-dev.N.M.
  final int? devPatch;

  /// The git tag that is this version's closest ancestor.
  final String gitTag;

  static GitTagVersion determine(
    Platform platform, {
    required Git git,
    String? workingDirectory,
    bool fetchTags = false,
    String gitRef = 'HEAD',
  }) {
    if (fetchTags) {
      final String channel = git
          .runSync(['symbolic-ref', '--short', 'HEAD'], workingDirectory: workingDirectory)
          .stdout
          .trim();
      if (!kDevelopmentChannels.contains(channel) && kOfficialChannels.contains(channel)) {
        globals.printTrace('Skipping request to fetchTags - on well known channel $channel.');
      } else {
        final String flutterGit =
            platform.environment['FLUTTER_GIT_URL'] ?? 'https://github.com/flutter/flutter.git';
        git.runSync(['fetch', flutterGit, '--tags', '-f'], workingDirectory: workingDirectory);
      }
    }
    // find all tags attached to the given [gitRef]. These are returned in alphabetical order, so
    // we reverse the set of tags to examine the most recent tag versions first.
    final List<String> tags = git
        .runSync(['tag', '--points-at', gitRef], workingDirectory: workingDirectory)
        .stdout
        .trim()
        .split('\n')
        .reversed
        .toList();

    // Check first for a stable tag
    final stableTagPattern = RegExp(r'^\d+\.\d+\.\d+$');
    for (final tag in tags) {
      if (stableTagPattern.hasMatch(tag.trim())) {
        return parse(tag);
      }
    }
    // Next check for a dev tag
    final devTagPattern = RegExp(r'^\d+\.\d+\.\d+-\d+\.\d+\.pre$');
    for (final tag in tags) {
      if (devTagPattern.hasMatch(tag.trim())) {
        return parse(tag);
      }
    }

    // If we don't exist in a tag, use git to find the latest tag.
    return _useNewestTagAndCommitsPastFallback(
      git: git,
      workingDirectory: workingDirectory,
      gitRef: gitRef,
    );
  }

  static GitTagVersion _useNewestTagAndCommitsPastFallback({
    required Git git,
    required String? workingDirectory,
    required String gitRef,
  }) {
    final String latestTag = git
        .runSync([
          'for-each-ref',
          '--sort=-v:refname',
          '--count=1',
          '--format=%(refname:short)',
          'refs/tags/[0-9]*.*.*',
        ], workingDirectory: workingDirectory)
        .stdout
        .trim();

    final String ancestorRef = git
        .runSync(['merge-base', gitRef, latestTag], workingDirectory: workingDirectory)
        .stdout
        .trim();

    final String commitCount = git
        .runSync([
          'rev-list',
          '--count',
          '$ancestorRef..$gitRef',
        ], workingDirectory: workingDirectory)
        .stdout
        .trim();

    return parse('$latestTag-$commitCount');
  }

  /// Parse a version string.
  ///
  /// The version string can either be an exact release tag (e.g. '1.2.3' for
  /// stable or 1.2.3-4.5.pre for a dev) or the output of `git describe` (e.g.
  /// for commit abc123 that is 6 commits after tag 1.2.3-4.5.pre, git would
  /// return '1.2.3-4.5.pre-6-gabc123').
  static GitTagVersion parseVersion(String version) {
    final versionPattern = RegExp(
      r'^(\d+)\.(\d+)\.(\d+)(-\d+\.\d+\.pre)?(?:[-\.](\d+)(?:-g([a-f0-9]+))?)?$',
    );
    final Match? match = versionPattern.firstMatch(version.trim());
    if (match == null) {
      return const GitTagVersion.unknown();
    }

    final List<String?> matchGroups = match.groups(<int>[1, 2, 3, 4, 5, 6]);
    final int? x = matchGroups[0] == null ? null : int.tryParse(matchGroups[0]!);
    final int? y = matchGroups[1] == null ? null : int.tryParse(matchGroups[1]!);
    final int? z = matchGroups[2] == null ? null : int.tryParse(matchGroups[2]!);
    final String? devString = matchGroups[3];
    int? devVersion, devPatch;
    if (devString != null) {
      final Match? devMatch = RegExp(r'^-(\d+)\.(\d+)\.pre$').firstMatch(devString);
      final List<String?>? devGroups = devMatch?.groups(<int>[1, 2]);
      devVersion = devGroups?[0] == null ? null : int.tryParse(devGroups![0]!);
      devPatch = devGroups?[1] == null ? null : int.tryParse(devGroups![1]!);
    }
    // count of commits past last tagged version
    final int? commits = matchGroups[4] == null ? 0 : int.tryParse(matchGroups[4]!);
    final String hash = matchGroups[5] ?? '';

    return GitTagVersion(
      x: x,
      y: y,
      z: z,
      devVersion: devVersion,
      devPatch: devPatch,
      commits: commits,
      hash: hash,
      gitTag: '$x.$y.$z${devString ?? ''}', // e.g. 1.2.3-4.5.pre
    );
  }

  @visibleForTesting
  static GitTagVersion parse(String version) {
    GitTagVersion gitTagVersion;

    gitTagVersion = parseVersion(version);
    if (gitTagVersion != const GitTagVersion.unknown()) {
      return gitTagVersion;
    }
    globals.printTrace('Could not interpret results of "git describe": $version');
    return const GitTagVersion.unknown();
  }

  String frameworkVersionFor(String revision) {
    if (x == null || y == null || z == null || !revision.startsWith(hash)) {
      return kUnknownFrameworkVersion;
    }
    if (commits == 0) {
      return gitTag;
    }
    if (hotfix != null) {
      // This is an unexpected state where untagged commits exist past a hotfix
      return '$x.$y.$z+hotfix.${hotfix! + 1}.pre-$commits';
    }
    if (devPatch != null && devVersion != null) {
      // The next tag that will contain this commit will be the next candidate
      // branch, which will increment the devVersion.
      return '$x.$y.0-${devVersion! + 1}.0.pre-$commits';
    }
    return '$x.$y.${z! + 1}-0.0.pre-$commits';
  }
}

enum VersionCheckResult {
  /// Unable to check whether a new version is available, possibly due to
  /// a connectivity issue.
  unknown,

  /// The current version is up to date.
  versionIsCurrent,

  /// A newer version is available.
  newVersionAvailable,
}

/// Determine whether or not the provided [version] is "fresh" and notify the user if appropriate.
///
/// To initiate the validation check, call [run].
///
/// We do not want to check with the upstream git remote for newer commits on
/// every tool invocation, as this would significantly slow down running tool
/// commands. Thus, the tool writes to the [VersionCheckStamp] every time that
/// it actually has fetched commits from upstream, and this validator only
/// checks again if it has been more than [checkAgeConsideredUpToDate] since the
/// last fetch.
///
/// We do not want to notify users with "reasonably" fresh versions about new
/// releases. The method [versionAgeConsideredUpToDate] defines a different
/// duration of freshness for each channel. If [localFrameworkCommitDate] is
/// newer than this duration, then we do not show the warning.
///
/// We do not want to annoy users who intentionally disregard the warning and
/// choose not to upgrade. Thus, we only show the message if it has been more
/// than [maxTimeSinceLastWarning] since the last time the user saw the warning.
class VersionFreshnessValidator {
  VersionFreshnessValidator({
    required this.version,
    required this.localFrameworkCommitDate,
    required this.clock,
    required this.cache,
    required this.logger,
    this.latestFlutterCommitDate,
    this.pauseTime = Duration.zero,
  });

  final FlutterVersion version;
  final DateTime localFrameworkCommitDate;
  final SystemClock clock;
  final Cache cache;
  final Logger logger;
  final Duration pauseTime;
  final DateTime? latestFlutterCommitDate;

  late final DateTime now = clock.now();
  late final Duration frameworkAge = now.difference(localFrameworkCommitDate);

  /// The amount of time we wait before pinging the server to check for the
  /// availability of a newer version of Flutter.
  @visibleForTesting
  static const checkAgeConsideredUpToDate = Duration(days: 3);

  /// The amount of time we wait between issuing a warning.
  ///
  /// This is to avoid annoying users who are unable to upgrade right away.
  @visibleForTesting
  static const maxTimeSinceLastWarning = Duration(days: 1);

  /// The amount of time we pause for to let the user read the message about
  /// outdated Flutter installation.
  ///
  /// This can be customized in tests to speed them up.
  @visibleForTesting
  static Duration timeToPauseToLetUserReadTheMessage = const Duration(seconds: 2);

  // We show a warning if either we know there is a new remote version, or we
  // couldn't tell but the local version is outdated.
  @visibleForTesting
  bool canShowWarning(VersionCheckResult remoteVersionStatus) {
    final bool installationSeemsOutdated =
        frameworkAge > versionAgeConsideredUpToDate(version.channel);
    if (remoteVersionStatus == VersionCheckResult.newVersionAvailable) {
      return true;
    }
    if (!installationSeemsOutdated) {
      return false;
    }
    return remoteVersionStatus == VersionCheckResult.unknown;
  }

  /// We warn the user if the age of their Flutter installation is greater than
  /// this duration. The durations are slightly longer than the expected release
  /// cadence for each channel, to give the user a grace period before they get
  /// notified.
  ///
  /// For example, for the beta channel, this is set to eight weeks because
  /// beta releases happen approximately every month.
  @visibleForTesting
  static Duration versionAgeConsideredUpToDate(String channel) {
    return switch (channel) {
      'stable' => const Duration(days: 365 ~/ 2), // Six months
      'beta' => const Duration(days: 7 * 8), // Eight weeks
      _ => const Duration(days: 7 * 3), // Three weeks
    };
  }

  /// Execute validations and print warning to [logger] if necessary.
  Future<void> run() async {
    // Get whether there's a newer version on the remote. This only goes
    // to the server if we haven't checked recently so won't happen on every
    // command.
    final VersionCheckResult remoteVersionStatus;

    if (latestFlutterCommitDate == null) {
      remoteVersionStatus = VersionCheckResult.unknown;
    } else {
      if (latestFlutterCommitDate!.isAfter(localFrameworkCommitDate)) {
        remoteVersionStatus = VersionCheckResult.newVersionAvailable;
      } else {
        remoteVersionStatus = VersionCheckResult.versionIsCurrent;
      }
    }

    // Do not load the stamp before the above server check as it may modify the stamp file.
    final VersionCheckStamp stamp = await VersionCheckStamp.load(cache, logger);
    final DateTime lastTimeWarningWasPrinted =
        stamp.lastTimeWarningWasPrinted ?? clock.ago(maxTimeSinceLastWarning * 2);
    final bool beenAWhileSinceWarningWasPrinted =
        now.difference(lastTimeWarningWasPrinted) > maxTimeSinceLastWarning;
    if (!beenAWhileSinceWarningWasPrinted) {
      return;
    }

    final bool canShowWarningResult = canShowWarning(remoteVersionStatus);

    if (!canShowWarningResult) {
      return;
    }

    // By this point, we should show the update message
    final String updateMessage;
    switch (remoteVersionStatus) {
      case VersionCheckResult.newVersionAvailable:
        updateMessage = _newVersionAvailableMessage;
      case VersionCheckResult.versionIsCurrent:
      case VersionCheckResult.unknown:
        updateMessage = versionOutOfDateMessage(frameworkAge);
    }

    logger.printBox(updateMessage);
    await Future.wait<void>(<Future<void>>[
      stamp.store(newTimeWarningWasPrinted: now, cache: cache),
      Future<void>.delayed(pauseTime),
    ]);
  }
}

@visibleForTesting
String versionOutOfDateMessage(Duration frameworkAge) {
  return '''
WARNING: your installation of Flutter is ${frameworkAge.inDays} days old.

To update to the latest version, run "flutter upgrade".''';
}

const _newVersionAvailableMessage = '''
A new version of Flutter is available!

To update to the latest version, run "flutter upgrade".''';

/// Data class for parsing engine_stamp.json.
@visibleForTesting
final class FlutterEngineStampFromFile {
  FlutterEngineStampFromFile._({
    required this.buildDate,
    required this.gitRevision,
    required this.gitRevisionDate,
    required this.contentHash,
  });

  /// General time when the engine artifacts were built.
  final DateTime buildDate;

  /// The git commit sha for these engine artifacts.
  final String gitRevision;

  /// The date of the [gitRevision] commit.
  final DateTime gitRevisionDate;

  /// The content-aware hash for this build.
  ///
  /// This hash helps uniquely identify engine changes and reduce artifact builds.
  final String contentHash;

  /// Attempt to parse [jsonFile] for `engine_stamp.json` values.
  static FlutterEngineStampFromFile? tryParseFromFile(File jsonFile) {
    final Map<String, Object?> data;
    try {
      data = json.decode(jsonFile.readAsStringSync()) as Map<String, Object?>;

      if (data case {
        'build_time_ms': final int buildTimeMs,
        'git_revision': final String gitRevision,
        'git_revision_date': final String gitRevisionDate,
        'content_hash': final String contentHash,
      }) {
        return FlutterEngineStampFromFile._(
          buildDate: DateTime.fromMillisecondsSinceEpoch(buildTimeMs),
          gitRevision: gitRevision,
          gitRevisionDate: DateTime.parse(gitRevisionDate),
          contentHash: contentHash,
        );
      }
      // ignore: avoid_catches_without_on_clauses
    } catch (_) {
      return null;
    }
    return null;
  }
}
