// 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 'plugin_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 PluginCommand {
  /// 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 await 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')}';
  }
}
