// Copyright 2013 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 'dart:async';

import 'package:colorize/colorize.dart';
import 'package:file/file.dart';
import 'package:git/git.dart';
import 'package:path/path.dart' as p;
import 'package:platform/platform.dart';
import 'package:pub_semver/pub_semver.dart';

import 'core.dart';
import 'package_command.dart';
import 'process_runner.dart';
import 'repository_package.dart';

/// Enumeration options for package looping commands.
enum PackageLoopingType {
  /// Only enumerates the top level packages, without including any of their
  /// subpackages.
  topLevelOnly,

  /// Enumerates the top level packages and any example packages they contain.
  includeExamples,

  /// Enumerates all packages recursively, including both example and
  /// non-example subpackages.
  includeAllSubpackages,
}

/// Possible outcomes of a command run for a package.
enum RunState {
  /// The command succeeded for the package.
  succeeded,

  /// The command was skipped for the package.
  skipped,

  /// The command was skipped for the package because it was explicitly excluded
  /// in the command arguments.
  excluded,

  /// The command failed for the package.
  failed,
}

/// The result of a [runForPackage] call.
class PackageResult {
  /// A successful result.
  PackageResult.success() : this._(RunState.succeeded);

  /// A run that was skipped as explained in [reason].
  PackageResult.skip(String reason)
      : this._(RunState.skipped, <String>[reason]);

  /// A run that was excluded by the command invocation.
  PackageResult.exclude() : this._(RunState.excluded);

  /// A run that failed.
  ///
  /// If [errors] are provided, they will be listed in the summary, otherwise
  /// the summary will simply show that the package failed.
  PackageResult.fail([List<String> errors = const <String>[]])
      : this._(RunState.failed, errors);

  const PackageResult._(this.state, [this.details = const <String>[]]);

  /// The state the package run completed with.
  final RunState state;

  /// Information about the result:
  /// - For `succeeded`, this is empty.
  /// - For `skipped`, it contains a single entry describing why the run was
  ///   skipped.
  /// - For `failed`, it contains zero or more specific error details to be
  ///   shown in the summary.
  final List<String> details;
}

/// An abstract base class for a command that iterates over a set of packages
/// controlled by a standard set of flags, running some actions on each package,
/// and collecting and reporting the success/failure of those actions.
abstract class PackageLoopingCommand extends PackageCommand {
  /// Creates a command to operate on [packagesDir] with the given environment.
  PackageLoopingCommand(
    Directory packagesDir, {
    ProcessRunner processRunner = const ProcessRunner(),
    Platform platform = const LocalPlatform(),
    GitDir? gitDir,
  }) : super(packagesDir,
            processRunner: processRunner, platform: platform, gitDir: gitDir) {
    argParser.addOption(
      _skipByFlutterVersionArg,
      help: 'Skip any packages that require a Flutter version newer than '
          'the provided version.',
    );
    argParser.addOption(
      _skipByDartVersionArg,
      help: 'Skip any packages that require a Dart version newer than '
          'the provided version.',
    );
  }

  static const String _skipByFlutterVersionArg =
      'skip-if-not-supporting-flutter-version';
  static const String _skipByDartVersionArg =
      'skip-if-not-supporting-dart-version';

  /// Packages that had at least one [logWarning] call.
  final Set<PackageEnumerationEntry> _packagesWithWarnings =
      <PackageEnumerationEntry>{};

  /// Number of warnings that happened outside of a [runForPackage] call.
  int _otherWarningCount = 0;

  /// The package currently being run by [runForPackage].
  PackageEnumerationEntry? _currentPackageEntry;

  /// Called during [run] before any calls to [runForPackage]. This provides an
  /// opportunity to fail early if the command can't be run (e.g., because the
  /// arguments are invalid), and to set up any run-level state.
  Future<void> initializeRun() async {}

  /// Returns the packages to process. By default, this returns the packages
  /// defined by the standard tooling flags and the [inculdeSubpackages] option,
  /// but can be overridden for custom package enumeration.
  ///
  /// Note: Consistent behavior across commands whenever possibel is a goal for
  /// this tool, so this should be overridden only in rare cases.
  Stream<PackageEnumerationEntry> getPackagesToProcess() async* {
    switch (packageLoopingType) {
      case PackageLoopingType.topLevelOnly:
        yield* getTargetPackages(filterExcluded: false);
        break;
      case PackageLoopingType.includeExamples:
        await for (final PackageEnumerationEntry packageEntry
            in getTargetPackages(filterExcluded: false)) {
          yield packageEntry;
          yield* Stream<PackageEnumerationEntry>.fromIterable(packageEntry
              .package
              .getExamples()
              .map((RepositoryPackage package) => PackageEnumerationEntry(
                  package,
                  excluded: packageEntry.excluded)));
        }
        break;
      case PackageLoopingType.includeAllSubpackages:
        yield* getTargetPackagesAndSubpackages(filterExcluded: false);
        break;
    }
  }

  /// Runs the command for [package], returning a list of errors.
  ///
  /// Errors may either be an empty string if there is no context that should
  /// be included in the final error summary (e.g., a command that only has a
  /// single failure mode), or strings that should be listed for that package
  /// in the final summary. An empty list indicates success.
  Future<PackageResult> runForPackage(RepositoryPackage package);

  /// Called during [run] after all calls to [runForPackage]. This provides an
  /// opportunity to do any cleanup of run-level state.
  Future<void> completeRun() async {}

  /// If [captureOutput], this is called just before exiting with all captured
  /// [output].
  Future<void> handleCapturedOutput(List<String> output) async {}

  /// Whether or not the output (if any) of [runForPackage] is long, or short.
  ///
  /// This changes the logging that happens at the start of each package's
  /// run; long output gets a banner-style message to make it easier to find,
  /// while short output gets a single-line entry.
  ///
  /// When this is false, runForPackage output should be indented if possible,
  /// to make the output structure easier to follow.
  bool get hasLongOutput => true;

  /// Whether to loop over top-level packages only, or some or all of their
  /// sub-packages as well.
  PackageLoopingType get packageLoopingType => PackageLoopingType.topLevelOnly;

  /// The text to output at the start when reporting one or more failures.
  /// This will be followed by a list of packages that reported errors, with
  /// the per-package details if any.
  ///
  /// This only needs to be overridden if the summary should provide extra
  /// context.
  String get failureListHeader => 'The following packages had errors:';

  /// The text to output at the end when reporting one or more failures. This
  /// will be printed immediately after the a list of packages that reported
  /// errors.
  ///
  /// This only needs to be overridden if the summary should provide extra
  /// context.
  String get failureListFooter => 'See above for full details.';

  /// The summary string used for a successful run in the final overview output.
  String get successSummaryMessage => 'ran';

  /// If true, all printing (including the summary) will be redirected to a
  /// buffer, and provided in a call to [handleCapturedOutput] at the end of
  /// the run.
  ///
  /// Capturing output will disable any colorizing of output from this base
  /// class.
  bool get captureOutput => false;

  // ----------------------------------------

  /// Logs that a warning occurred, and prints `warningMessage` in yellow.
  ///
  /// Warnings are not surfaced in CI summaries, so this is only useful for
  /// highlighting something when someone is already looking though the log
  /// messages. DO NOT RELY on someone noticing a warning; instead, use it for
  /// things that might be useful to someone debugging an unexpected result.
  void logWarning(String warningMessage) {
    _printColorized(warningMessage, Styles.YELLOW);
    if (_currentPackageEntry != null) {
      _packagesWithWarnings.add(_currentPackageEntry!);
    } else {
      ++_otherWarningCount;
    }
  }

  /// Returns the relative path from [from] to [entity] in Posix style.
  ///
  /// This should be used when, for example, printing package-relative paths in
  /// status or error messages.
  String getRelativePosixPath(
    FileSystemEntity entity, {
    required Directory from,
  }) =>
      p.posix.joinAll(path.split(path.relative(entity.path, from: from.path)));

  /// The suggested indentation for printed output.
  String get indentation => hasLongOutput ? '' : '  ';

  // ----------------------------------------

  @override
  Future<void> run() async {
    bool succeeded;
    if (captureOutput) {
      final List<String> output = <String>[];
      final ZoneSpecification logSwitchSpecification = ZoneSpecification(
          print: (Zone self, ZoneDelegate parent, Zone zone, String message) {
        output.add(message);
      });
      succeeded = await runZoned<Future<bool>>(_runInternal,
          zoneSpecification: logSwitchSpecification);
      await handleCapturedOutput(output);
    } else {
      succeeded = await _runInternal();
    }

    if (!succeeded) {
      throw ToolExit(exitCommandFoundErrors);
    }
  }

  Future<bool> _runInternal() async {
    _packagesWithWarnings.clear();
    _otherWarningCount = 0;
    _currentPackageEntry = null;

    final String minFlutterVersionArg = getStringArg(_skipByFlutterVersionArg);
    final Version? minFlutterVersion = minFlutterVersionArg.isEmpty
        ? null
        : Version.parse(minFlutterVersionArg);
    final String minDartVersionArg = getStringArg(_skipByDartVersionArg);
    final Version? minDartVersion =
        minDartVersionArg.isEmpty ? null : Version.parse(minDartVersionArg);

    final DateTime runStart = DateTime.now();

    await initializeRun();

    final List<PackageEnumerationEntry> targetPackages =
        await getPackagesToProcess().toList();

    final Map<PackageEnumerationEntry, PackageResult> results =
        <PackageEnumerationEntry, PackageResult>{};
    for (final PackageEnumerationEntry entry in targetPackages) {
      final DateTime packageStart = DateTime.now();
      _currentPackageEntry = entry;
      _printPackageHeading(entry, startTime: runStart);

      // Command implementations should never see excluded packages; they are
      // included at this level only for logging.
      if (entry.excluded) {
        results[entry] = PackageResult.exclude();
        continue;
      }

      PackageResult result;
      try {
        result = await _runForPackageIfSupported(entry.package,
            minFlutterVersion: minFlutterVersion,
            minDartVersion: minDartVersion);
      } catch (e, stack) {
        printError(e.toString());
        printError(stack.toString());
        result = PackageResult.fail(<String>['Unhandled exception']);
      }
      if (result.state == RunState.skipped) {
        _printColorized('${indentation}SKIPPING: ${result.details.first}',
            Styles.DARK_GRAY);
      }
      results[entry] = result;

      // Only log an elapsed time for long output; for short output, comparing
      // the relative timestamps of successive entries should be trivial.
      if (shouldLogTiming && hasLongOutput) {
        final Duration elapsedTime = DateTime.now().difference(packageStart);
        _printColorized(
            '\n[${entry.package.displayName} completed in '
            '${elapsedTime.inMinutes}m ${elapsedTime.inSeconds % 60}s]',
            Styles.DARK_GRAY);
      }
    }
    _currentPackageEntry = null;

    completeRun();

    print('\n');
    // If there were any errors reported, summarize them and exit.
    if (results.values
        .any((PackageResult result) => result.state == RunState.failed)) {
      _printFailureSummary(targetPackages, results);
      return false;
    }

    // Otherwise, print a summary of what ran for ease of auditing that all the
    // expected tests ran.
    _printRunSummary(targetPackages, results);

    print('\n');
    _printSuccess('No issues found!');
    return true;
  }

  /// Returns the result of running [runForPackage] if the package is supported
  /// by any run constraints, or a skip result if it is not.
  Future<PackageResult> _runForPackageIfSupported(
    RepositoryPackage package, {
    Version? minFlutterVersion,
    Version? minDartVersion,
  }) async {
    if (minFlutterVersion != null) {
      final Pubspec pubspec = package.parsePubspec();
      final VersionConstraint? flutterConstraint =
          pubspec.environment?['flutter'];
      if (flutterConstraint != null &&
          !flutterConstraint.allows(minFlutterVersion)) {
        return PackageResult.skip(
            'Does not support Flutter $minFlutterVersion');
      }
    }

    if (minDartVersion != null) {
      final Pubspec pubspec = package.parsePubspec();
      final VersionConstraint? dartConstraint = pubspec.environment?['sdk'];
      if (dartConstraint != null && !dartConstraint.allows(minDartVersion)) {
        return PackageResult.skip('Does not support Dart $minDartVersion');
      }
    }

    return runForPackage(package);
  }

  void _printSuccess(String message) {
    captureOutput ? print(message) : printSuccess(message);
  }

  void _printError(String message) {
    captureOutput ? print(message) : printError(message);
  }

  /// Prints the status message indicating that the command is being run for
  /// [package].
  ///
  /// Something is always printed to make it easier to distinguish between
  /// a command running for a package and producing no output, and a command
  /// not having been run for a package.
  void _printPackageHeading(PackageEnumerationEntry entry,
      {required DateTime startTime}) {
    final String packageDisplayName = entry.package.displayName;
    String heading = entry.excluded
        ? 'Not running for $packageDisplayName; excluded'
        : 'Running for $packageDisplayName';

    if (shouldLogTiming) {
      final Duration relativeTime = DateTime.now().difference(startTime);
      final String timeString = _formatDurationAsRelativeTime(relativeTime);
      heading =
          hasLongOutput ? '$heading [@$timeString]' : '[$timeString] $heading';
    }

    if (hasLongOutput) {
      heading = '''

============================================================
|| $heading
============================================================
''';
    } else if (!entry.excluded) {
      heading = '$heading...';
    }
    _printColorized(heading, entry.excluded ? Styles.DARK_GRAY : Styles.CYAN);
  }

  /// Prints a summary of packges run, packages skipped, and warnings.
  void _printRunSummary(List<PackageEnumerationEntry> packages,
      Map<PackageEnumerationEntry, PackageResult> results) {
    final Set<PackageEnumerationEntry> skippedPackages = results.entries
        .where((MapEntry<PackageEnumerationEntry, PackageResult> entry) =>
            entry.value.state == RunState.skipped)
        .map((MapEntry<PackageEnumerationEntry, PackageResult> entry) =>
            entry.key)
        .toSet();
    final int skipCount = skippedPackages.length +
        packages
            .where((PackageEnumerationEntry package) => package.excluded)
            .length;
    // Split the warnings into those from packages that ran, and those that
    // were skipped.
    final Set<PackageEnumerationEntry> skippedPackagesWithWarnings =
        _packagesWithWarnings.intersection(skippedPackages);
    final int skippedWarningCount = skippedPackagesWithWarnings.length;
    final int runWarningCount =
        _packagesWithWarnings.length - skippedWarningCount;

    final String runWarningSummary =
        runWarningCount > 0 ? ' ($runWarningCount with warnings)' : '';
    final String skippedWarningSummary =
        runWarningCount > 0 ? ' ($skippedWarningCount with warnings)' : '';
    print('------------------------------------------------------------');
    if (hasLongOutput) {
      _printPerPackageRunOverview(packages, skipped: skippedPackages);
    }
    print(
        'Ran for ${packages.length - skipCount} package(s)$runWarningSummary');
    if (skipCount > 0) {
      print('Skipped $skipCount package(s)$skippedWarningSummary');
    }
    if (_otherWarningCount > 0) {
      print('$_otherWarningCount warnings not associated with a package');
    }
  }

  /// Prints a one-line-per-package overview of the run results for each
  /// package.
  void _printPerPackageRunOverview(
      List<PackageEnumerationEntry> packageEnumeration,
      {required Set<PackageEnumerationEntry> skipped}) {
    print('Run overview:');
    for (final PackageEnumerationEntry entry in packageEnumeration) {
      final bool hadWarning = _packagesWithWarnings.contains(entry);
      Styles style;
      String summary;
      if (entry.excluded) {
        summary = 'excluded';
        style = Styles.DARK_GRAY;
      } else if (skipped.contains(entry)) {
        summary = 'skipped';
        style = hadWarning ? Styles.LIGHT_YELLOW : Styles.DARK_GRAY;
      } else {
        summary = successSummaryMessage;
        style = hadWarning ? Styles.YELLOW : Styles.GREEN;
      }
      if (hadWarning) {
        summary += ' (with warning)';
      }

      if (!captureOutput) {
        summary = (Colorize(summary)..apply(style)).toString();
      }
      print('  ${entry.package.displayName} - $summary');
    }
    print('');
  }

  /// Prints a summary of all of the failures from [results].
  void _printFailureSummary(List<PackageEnumerationEntry> packageEnumeration,
      Map<PackageEnumerationEntry, PackageResult> results) {
    const String indentation = '  ';
    _printError(failureListHeader);
    for (final PackageEnumerationEntry entry in packageEnumeration) {
      final PackageResult result = results[entry]!;
      if (result.state == RunState.failed) {
        final String errorIndentation = indentation * 2;
        String errorDetails = '';
        if (result.details.isNotEmpty) {
          errorDetails =
              ':\n$errorIndentation${result.details.join('\n$errorIndentation')}';
        }
        _printError('$indentation${entry.package.displayName}$errorDetails');
      }
    }
    _printError(failureListFooter);
  }

  /// Prints [message] in [color] unless [captureOutput] is set, in which case
  /// it is printed without color.
  void _printColorized(String message, Styles color) {
    if (captureOutput) {
      print(message);
    } else {
      print(Colorize(message)..apply(color));
    }
  }

  /// Returns a duration [d] formatted as minutes:seconds. Does not use hours,
  /// since time logging is primarily intended for CI, where durations should
  /// always be less than an hour.
  String _formatDurationAsRelativeTime(Duration d) {
    return '${d.inMinutes}:${(d.inSeconds % 60).toString().padLeft(2, '0')}';
  }
}
