// 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 'dart:convert';
import 'dart:io';
import 'dart:math' as math;

import 'package:archive/archive_io.dart';
import 'package:args/args.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:http/http.dart' as http;
import 'package:intl/intl.dart';
import 'package:meta/meta.dart';
import 'package:path/path.dart' as path;
import 'package:platform/platform.dart';
import 'package:process/process.dart';
import 'package:pub_semver/pub_semver.dart';

import 'dartdoc_checker.dart';

const String kDummyPackageName = 'Flutter';
const String kPlatformIntegrationPackageName = 'platform_integration';

/// Additional package dependencies that we want to have in the docs,
/// but not actually depend on them.
const Map<String, (String path, String version)> kFakeDependencies = <String, (String, String)>{
    'flutter_gpu': ('flutter_gpu/gpu.dart', '\n    sdk: flutter'),
  };

class PlatformDocsSection {
  const PlatformDocsSection({
    required this.zipName,
    required this.sectionName,
    required this.checkFile,
    required this.subdir,
  });
  final String zipName;
  final String sectionName;
  final String checkFile;
  final String subdir;
}

const Map<String, PlatformDocsSection> kPlatformDocs = <String, PlatformDocsSection>{
  'android': PlatformDocsSection(
    zipName: 'android-javadoc.zip',
    sectionName: 'Android',
    checkFile: 'io/flutter/embedding/android/FlutterView.html',
    subdir: 'javadoc',
  ),
  'ios': PlatformDocsSection(
    zipName: 'ios-docs.zip',
    sectionName: 'iOS',
    checkFile: 'interface_flutter_view.html',
    subdir: 'ios-embedder',
  ),
  'macos': PlatformDocsSection(
    zipName: 'macos-docs.zip',
    sectionName: 'macOS',
    checkFile: 'interface_flutter_view.html',
    subdir: 'macos-embedder',
  ),
  'linux': PlatformDocsSection(
    zipName: 'linux-docs.zip',
    sectionName: 'Linux',
    checkFile: 'struct___fl_view.html',
    subdir: 'linux-embedder',
  ),
  'windows': PlatformDocsSection(
    zipName: 'windows-docs.zip',
    sectionName: 'Windows',
    checkFile: 'classflutter_1_1_flutter_view.html',
    subdir: 'windows-embedder',
  ),
  'impeller': PlatformDocsSection(
    zipName: 'impeller-docs.zip',
    sectionName: 'Impeller',
    checkFile: 'classimpeller_1_1_canvas.html',
    subdir: 'impeller',
  ),
};

/// This script will generate documentation for the packages in `packages/` and
/// write the documentation to the output directory specified on the command
/// line.
///
/// This script also updates the index.html file so that it can be placed at the
/// root of api.flutter.dev. The files are kept inside of
/// api.flutter.dev/flutter, so we need to manipulate paths a bit. See
/// https://github.com/flutter/flutter/issues/3900 for more info.
///
/// This will only work on UNIX systems, not Windows. It requires that 'git',
/// 'zip', and 'tar' be in the PATH. It requires that 'flutter' has been run
/// previously. It uses the version of Dart downloaded by the 'flutter' tool in
/// this repository and will fail if that is absent.
Future<void> main(List<String> arguments) async {
  const FileSystem filesystem = LocalFileSystem();
  const ProcessManager processManager = LocalProcessManager();
  const Platform platform = LocalPlatform();

  // The place to find customization files and configuration files for docs
  // generation.
  final Directory docsRoot =
      FlutterInformation.instance.getFlutterRoot().childDirectory('dev').childDirectory('docs').absolute;
  final ArgParser argParser = _createArgsParser(
    publishDefault: docsRoot.childDirectory('doc').path,
  );
  final ArgResults args = argParser.parse(arguments);
  if (args['help'] as bool) {
    print('Usage:');
    print(argParser.usage);
    exit(0);
  }

  final Directory publishRoot = filesystem.directory(args['output-dir']! as String).absolute;
  final Directory packageRoot = publishRoot.parent;
  if (!filesystem.directory(packageRoot).existsSync()) {
    filesystem.directory(packageRoot).createSync(recursive: true);
  }

  if (!filesystem.directory(publishRoot).existsSync()) {
    filesystem.directory(publishRoot).createSync(recursive: true);
  }

  final Configurator configurator = Configurator(
    publishRoot: publishRoot,
    packageRoot: packageRoot,
    docsRoot: docsRoot,
    filesystem: filesystem,
    processManager: processManager,
    platform: platform,
  );
  configurator.generateConfiguration();

  final PlatformDocGenerator platformGenerator = PlatformDocGenerator(outputDir: publishRoot, filesystem: filesystem);
  await platformGenerator.generatePlatformDocs();

  final DartdocGenerator dartdocGenerator = DartdocGenerator(
    publishRoot: publishRoot,
    packageRoot: packageRoot,
    docsRoot: docsRoot,
    filesystem: filesystem,
    processManager: processManager,
    useJson: args['json'] as bool? ?? true,
    validateLinks: args['validate-links']! as bool,
    verbose: args['verbose'] as bool? ?? false,
  );

  await dartdocGenerator.generateDartdoc();
  await configurator.generateOfflineAssetsIfNeeded();
}

ArgParser _createArgsParser({required String publishDefault}) {
  final ArgParser parser = ArgParser();
  parser.addFlag('help', abbr: 'h', negatable: false, help: 'Show command help.');
  parser.addFlag('verbose',
      defaultsTo: true,
      help: 'Whether to report all error messages (on) or attempt to '
          'filter out some known false positives (off). Shut this off '
          'locally if you want to address Flutter-specific issues.');
  parser.addFlag('json', help: 'Display json-formatted output from dartdoc and skip stdout/stderr prefixing.');
  parser.addFlag('validate-links', help: 'Display warnings for broken links generated by dartdoc (slow)');
  parser.addOption('output-dir', defaultsTo: publishDefault, help: 'Sets the output directory for the documentation.');
  return parser;
}

/// A class used to configure the staging area for building the docs in.
///
/// The [generateConfiguration] function generates a dummy package with a
/// pubspec. It copies any assets and customization files from the framework
/// repo. It creates a metadata file for searches.
///
/// Once the docs have been generated, [generateOfflineAssetsIfNeeded] will
/// create offline assets like Dash/Zeal docsets and an offline ZIP file of the
/// site if the build is a CI build that is not a presubmit build.
class Configurator {
  Configurator({
    required this.docsRoot,
    required this.publishRoot,
    required this.packageRoot,
    required this.filesystem,
    required this.processManager,
    required this.platform,
  });

  /// The root of the directory in the Flutter repo where configuration data is
  /// stored.
  final Directory docsRoot;

  /// The root of the output area for the dartdoc docs.
  ///
  /// Typically this is a "doc" subdirectory under the [packageRoot].
  final Directory publishRoot;

  /// The root of the staging area for creating docs.
  final Directory packageRoot;

  /// The [FileSystem] object used to create [File] and [Directory] objects.
  final FileSystem filesystem;

  /// The [ProcessManager] object used to invoke external processes.
  ///
  /// Can be replaced by tests to have a fake process manager.
  final ProcessManager processManager;

  /// The [Platform] to use for this run.
  ///
  /// Can be replaced by tests to test behavior on different platforms.
  final Platform platform;

  void generateConfiguration() {
    final Version version = FlutterInformation.instance.getFlutterVersion();
    _createDummyPubspec();
    _createDummyLibrary();
    _createPageFooter(packageRoot, version);
    _copyCustomizations();
    _createSearchMetadata(
        docsRoot.childDirectory('lib').childFile('opensearch.xml'), publishRoot.childFile('opensearch.xml'));
  }

  Future<void> generateOfflineAssetsIfNeeded() async {
    // Only create the offline docs if we're running in a non-presubmit build:
    // it takes too long otherwise.
    if (platform.environment.containsKey('LUCI_CI') && (platform.environment['LUCI_PR'] ?? '').isEmpty) {
      _createOfflineZipFile();
      await _createDocset();
      _moveOfflineIntoPlace();
      _createRobotsTxt();
    }
  }

  /// Returns import or on-disk paths for all libraries in the Flutter SDK.
  Iterable<String> _libraryRefs() sync* {
    for (final Directory dir in findPackages(filesystem)) {
      final String dirName = dir.basename;
      for (final FileSystemEntity file in dir.childDirectory('lib').listSync()) {
        if (file is File && file.path.endsWith('.dart')) {
          yield '$dirName/${file.basename}';
        }
      }
    }

    // Add a fake references for libraries that we don't actually depend on so
    // that they will be included in the docs.
    for (final String package in kFakeDependencies.keys) {
      yield kFakeDependencies[package]!.$1;
    }

    // Add a fake package for platform integration APIs.
    yield '$kPlatformIntegrationPackageName/android.dart';
    yield '$kPlatformIntegrationPackageName/ios.dart';
    yield '$kPlatformIntegrationPackageName/macos.dart';
    yield '$kPlatformIntegrationPackageName/linux.dart';
    yield '$kPlatformIntegrationPackageName/windows.dart';
  }

  void _createDummyPubspec() {
    // Create the pubspec.yaml file.
    final List<String> pubspec = <String>[
      'name: $kDummyPackageName',
      'homepage: https://flutter.dev',
      'version: 0.0.0',
      'environment:',
      "  sdk: '>=3.2.0-0 <4.0.0'",
      'dependencies:',
      for (final String package in findPackageNames(filesystem))
        '  $package:\n    sdk: flutter',
      '  $kPlatformIntegrationPackageName: 0.0.1',
      for (final String package in kFakeDependencies.keys)
        '  $package: ${kFakeDependencies[package]!.$2}',
      'dependency_overrides:',
      '  $kPlatformIntegrationPackageName:',
      '    path: ${docsRoot.childDirectory(kPlatformIntegrationPackageName).path}',
    ];

    packageRoot.childFile('pubspec.yaml').writeAsStringSync(pubspec.join('\n'));
  }

  void _createDummyLibrary() {
    final Directory libDir = packageRoot.childDirectory('lib');
    libDir.createSync();

    final StringBuffer contents = StringBuffer('library temp_doc;\n\n');
    for (final String libraryRef in _libraryRefs()) {
      contents.writeln("import 'package:$libraryRef';");
    }
    packageRoot.childDirectory('lib')
      ..createSync(recursive: true)
      ..childFile('temp_doc.dart').writeAsStringSync(contents.toString());
  }

  void _createPageFooter(Directory footerPath, Version version) {
    final String timestamp = DateFormat('yyyy-MM-dd HH:mm').format(DateTime.now());
    String channel = FlutterInformation.instance.getBranchName();
    // Backward compatibility: Still support running on "master", but pretend it is "main".
    if (channel == 'master') {
      channel = 'main';
    }
    final String gitRevision = FlutterInformation.instance.getFlutterRevision();
    final String channelOut = channel.isEmpty ? '' : '• $channel';
    footerPath.childFile('footer.html').writeAsStringSync('<script src="footer.js"></script>');
    publishRoot.childDirectory('flutter').childFile('footer.js')
      ..createSync(recursive: true)
      ..writeAsStringSync('''
(function() {
  var span = document.querySelector('footer>span');
  if (span) {
    span.innerText = 'Flutter $version • $timestamp • $gitRevision $channelOut';
  }
  var sourceLink = document.querySelector('a.source-link');
  if (sourceLink) {
    sourceLink.href = sourceLink.href.replace('/main/', '/$gitRevision/');
  }
})();
''');
  }

  void _copyCustomizations() {
    final List<String> files = <String>[
      'README.md',
      'analysis_options.yaml',
      'dartdoc_options.yaml',
    ];
    for (final String file in files) {
      final File source = docsRoot.childFile(file);
      final File destination = packageRoot.childFile(file);
      // Have to canonicalize because otherwise things like /foo/bar/baz and
      // /foo/../foo/bar/baz won't compare as identical.
      if (path.canonicalize(source.absolute.path) != path.canonicalize(destination.absolute.path)) {
        source.copySync(destination.path);
        print('Copied ${path.canonicalize(source.absolute.path)} to ${path.canonicalize(destination.absolute.path)}');
      }
    }
    final Directory assetsDir = filesystem.directory(publishRoot.childDirectory('assets'));
    final Directory assetSource = docsRoot.childDirectory('assets');
    if (path.canonicalize(assetSource.absolute.path) == path.canonicalize(assetsDir.absolute.path)) {
      // Don't try and copy the directory over itself.
      return;
    }
    if (assetsDir.existsSync()) {
      assetsDir.deleteSync(recursive: true);
    }
    if (assetSource.existsSync()) {
      copyDirectorySync(
        assetSource,
        assetsDir,
        onFileCopied: (File src, File dest) {
          print('Copied ${path.canonicalize(src.absolute.path)} to ${path.canonicalize(dest.absolute.path)}');
        },
        filesystem: filesystem,
      );
    }
  }

  /// Generates an OpenSearch XML description that can be used to add a custom
  /// search for Flutter API docs to the browser. Unfortunately, it has to know
  /// the URL to which site to search, so we customize it here based upon the
  /// branch name.
  void _createSearchMetadata(File templatePath, File metadataPath) {
    final String template = templatePath.readAsStringSync();
    final String branch = FlutterInformation.instance.getBranchName();
    final String metadata = template.replaceAll(
      '{SITE_URL}',
      branch == 'stable' ? 'https://api.flutter.dev/' : 'https://main-api.flutter.dev/',
    );
    metadataPath.parent.create(recursive: true);
    metadataPath.writeAsStringSync(metadata);
  }

  Future<void> _createDocset() async {
    // Must have dashing installed: go get -u github.com/technosophos/dashing
    // Dashing produces a LOT of log output (~30MB), so we collect it, and just
    // show the end of it if there was a problem.
    print('${DateTime.now().toUtc()}: Building Flutter docset.');

    // If dashing gets stuck, Cirrus will time out the build after an hour, and we
    // never get to see the logs. Thus, we run it in the background and tail the
    // logs only if it fails.
    final ProcessWrapper result = ProcessWrapper(
      await processManager.start(
        <String>[
          'dashing',
          'build',
          '--source',
          publishRoot.path,
          '--config',
          docsRoot.childFile('dashing.json').path,
        ],
        workingDirectory: packageRoot.path,
      ),
    );
    final List<int> buffer = <int>[];
    result.stdout.listen(buffer.addAll);
    result.stderr.listen(buffer.addAll);
    // If the dashing process exited with an error, print the last 200 lines of stderr and exit.
    final int exitCode = await result.done;
    if (exitCode != 0) {
      print('Dashing docset generation failed with code $exitCode');
      final List<String> output = systemEncoding.decode(buffer).split('\n');
      print(output.sublist(math.max(output.length - 200, 0)).join('\n'));
      exit(exitCode);
    }
    buffer.clear();

    // Copy the favicon file to the output directory.
    final File faviconFile =
        publishRoot.childDirectory('flutter').childDirectory('static-assets').childFile('favicon.png');
    final File iconFile = packageRoot.childDirectory('flutter.docset').childFile('icon.png');
    faviconFile
      ..createSync(recursive: true)
      ..copySync(iconFile.path);

    // Post-process the dashing output.
    final File infoPlist =
        packageRoot.childDirectory('flutter.docset').childDirectory('Contents').childFile('Info.plist');
    String contents = infoPlist.readAsStringSync();

    // Since I didn't want to add the XML package as a dependency just for this,
    // I just used a regular expression to make this simple change.
    final RegExp findRe = RegExp(r'(\s*<key>DocSetPlatformFamily</key>\s*<string>)[^<]+(</string>)', multiLine: true);
    contents = contents.replaceAllMapped(findRe, (Match match) {
      return '${match.group(1)}dartlang${match.group(2)}';
    });
    infoPlist.writeAsStringSync(contents);
    final Directory offlineDir = publishRoot.childDirectory('offline');
    if (!offlineDir.existsSync()) {
      offlineDir.createSync(recursive: true);
    }
    tarDirectory(packageRoot, offlineDir.childFile('flutter.docset.tar.gz'), processManager: processManager);

    // Write the Dash/Zeal XML feed file.
    final bool isStable = platform.environment['LUCI_BRANCH'] == 'stable';
    offlineDir.childFile('flutter.xml').writeAsStringSync('<entry>\n'
        '  <version>${FlutterInformation.instance.getFlutterVersion()}</version>\n'
        '  <url>https://${isStable ? '' : 'main-'}api.flutter.dev/offline/flutter.docset.tar.gz</url>\n'
        '</entry>\n');
  }

  // Creates the offline ZIP file containing all of the website HTML files.
  void _createOfflineZipFile() {
    print('${DateTime.now().toLocal()}: Creating offline docs archive.');
    zipDirectory(publishRoot, packageRoot.childFile('flutter.docs.zip'), processManager: processManager);
  }

  // Moves the generated offline archives into the publish directory so that
  // they can be included in the output ZIP file.
  void _moveOfflineIntoPlace() {
    print('${DateTime.now().toUtc()}: Moving offline docs into place.');
    final Directory offlineDir = publishRoot.childDirectory('offline')..createSync(recursive: true);
    packageRoot.childFile('flutter.docs.zip').renameSync(offlineDir.childFile('flutter.docs.zip').path);
  }

  // Creates a robots.txt file that disallows indexing unless the branch is the
  // stable branch.
  void _createRobotsTxt() {
    final File robotsTxt = publishRoot.childFile('robots.txt');
    if (FlutterInformation.instance.getBranchName() == 'stable') {
      robotsTxt.writeAsStringSync('# All robots welcome!');
    } else {
      robotsTxt.writeAsStringSync('User-agent: *\nDisallow: /');
    }
  }
}

/// Runs Dartdoc inside of the given pre-prepared staging area, prepared by
/// [Configurator.generateConfiguration].
///
/// Performs a sanity check of the output once the generation is complete.
class DartdocGenerator {
  DartdocGenerator({
    required this.docsRoot,
    required this.publishRoot,
    required this.packageRoot,
    required this.filesystem,
    required this.processManager,
    this.useJson = true,
    this.validateLinks = true,
    this.verbose = false,
  });

  /// The root of the directory in the Flutter repo where configuration data is
  /// stored.
  final Directory docsRoot;

  /// The root of the output area for the dartdoc docs.
  ///
  /// Typically this is a "doc" subdirectory under the [packageRoot].
  final Directory publishRoot;

  /// The root of the staging area for creating docs.
  final Directory packageRoot;

  /// The [FileSystem] object used to create [File] and [Directory] objects.
  final FileSystem filesystem;

  /// The [ProcessManager] object used to invoke external processes.
  ///
  /// Can be replaced by tests to have a fake process manager.
  final ProcessManager processManager;

  /// Whether or not dartdoc should output an index.json file of the
  /// documentation.
  final bool useJson;

  // Whether or not to have dartdoc validate its own links.
  final bool validateLinks;

  /// Whether or not to filter overly verbose log output from dartdoc.
  final bool verbose;

  Future<void> generateDartdoc() async {
    final Directory flutterRoot = FlutterInformation.instance.getFlutterRoot();
    final Map<String, String> pubEnvironment = <String, String>{
      'FLUTTER_ROOT': flutterRoot.absolute.path,
    };

    // If there's a .pub-cache dir in the Flutter root, use that.
    final File pubCache = flutterRoot.childFile('.pub-cache');
    if (pubCache.existsSync()) {
      pubEnvironment['PUB_CACHE'] = pubCache.path;
    }

    // Run pub.
    ProcessWrapper process = ProcessWrapper(await runPubProcess(
      arguments: <String>['get'],
      workingDirectory: packageRoot,
      environment: pubEnvironment,
      filesystem: filesystem,
      processManager: processManager,
    ));
    printStream(process.stdout, prefix: 'pub:stdout: ');
    printStream(process.stderr, prefix: 'pub:stderr: ');
    final int code = await process.done;
    if (code != 0) {
      exit(code);
    }

    final Version version = FlutterInformation.instance.getFlutterVersion();

    // Verify which version of the global activated packages we're using.
    final ProcessResult versionResults = processManager.runSync(
      <String>[
        FlutterInformation.instance.getFlutterBinaryPath().path,
        'pub',
        'global',
        'list',
      ],
      workingDirectory: packageRoot.path,
      environment: pubEnvironment,
      stdoutEncoding: utf8,
    );
    print('');
    final Iterable<RegExpMatch> versionMatches =
        RegExp(r'^(?<name>dartdoc) (?<version>[^\s]+)', multiLine: true)
            .allMatches(versionResults.stdout as String);
    for (final RegExpMatch match in versionMatches) {
      print('${match.namedGroup('name')} version: ${match.namedGroup('version')}');
    }

    print('flutter version: $version\n');

    // Dartdoc warnings and errors in these packages are considered fatal.
    // All packages owned by flutter should be in the list.
    final List<String> flutterPackages = <String>[
      kDummyPackageName,
      kPlatformIntegrationPackageName,
      ...findPackageNames(filesystem),
      // TODO(goderbauer): Figure out how to only include `dart:ui` of
      // `sky_engine` below, https://github.com/dart-lang/dartdoc/issues/2278.
      // 'sky_engine',
    ];

    // Generate the documentation. We don't need to exclude flutter_tools in
    // this list because it's not in the recursive dependencies of the package
    // defined at packageRoot
    final List<String> dartdocArgs = <String>[
      'global',
      'run',
      '--enable-asserts',
      'dartdoc',
      '--output',
      publishRoot.childDirectory('flutter').path,
      '--allow-tools',
      if (useJson) '--json',
      if (validateLinks) '--validate-links' else '--no-validate-links',
      '--link-to-source-excludes',
      flutterRoot.childDirectory('bin').childDirectory('cache').path,
      '--link-to-source-root',
      flutterRoot.path,
      '--link-to-source-uri-template',
      'https://github.com/flutter/flutter/blob/main/%f%#L%l%',
      '--inject-html',
      '--use-base-href',
      '--header',
      docsRoot.childFile('styles.html').path,
      '--header',
      docsRoot.childFile('analytics-header.html').path,
      '--header',
      docsRoot.childFile('survey.html').path,
      '--header',
      docsRoot.childFile('snippets.html').path,
      '--header',
      docsRoot.childFile('opensearch.html').path,
      '--footer',
      docsRoot.childFile('analytics-footer.html').path,
      '--footer-text',
      packageRoot.childFile('footer.html').path,
      '--allow-warnings-in-packages',
      flutterPackages.join(','),
      '--exclude-packages',
      <String>[
        'analyzer',
        'args',
        'barback',
        'csslib',
        'flutter_goldens',
        'flutter_goldens_client',
        'front_end',
        'fuchsia_remote_debug_protocol',
        'glob',
        'html',
        'http_multi_server',
        'io',
        'isolate',
        'js',
        'kernel',
        'logging',
        'mime',
        'mockito',
        'node_preamble',
        'plugin',
        'shelf',
        'shelf_packages_handler',
        'shelf_static',
        'shelf_web_socket',
        'utf',
        'watcher',
        'yaml',
      ].join(','),
      '--exclude',
      <String>[
        'dart:io/network_policy.dart', // dart-lang/dartdoc#2437
        'package:Flutter/temp_doc.dart',
        'package:http/browser_client.dart',
        'package:intl/intl_browser.dart',
        'package:matcher/mirror_matchers.dart',
        'package:quiver/io.dart',
        'package:quiver/mirrors.dart',
        'package:vm_service_client/vm_service_client.dart',
        'package:web_socket_channel/html.dart',
      ].join(','),
      '--favicon',
      docsRoot.childFile('favicon.ico').absolute.path,
      '--package-order',
      'flutter,Dart,$kPlatformIntegrationPackageName,flutter_test,flutter_driver',
      '--auto-include-dependencies',
    ];

    String quote(String arg) => arg.contains(' ') ? "'$arg'" : arg;
    print('Executing: (cd "${packageRoot.path}" ; '
        '${FlutterInformation.instance.getFlutterBinaryPath().path} '
	'pub '
        '${dartdocArgs.map<String>(quote).join(' ')})');

    process = ProcessWrapper(await runPubProcess(
      arguments: dartdocArgs,
      workingDirectory: packageRoot,
      environment: pubEnvironment,
      processManager: processManager,
    ));
    printStream(
      process.stdout,
      prefix: useJson ? '' : 'dartdoc:stdout: ',
      filter: <Pattern>[
        if (!verbose) RegExp(r'^Generating docs for library '), // Unnecessary verbosity
      ],
    );
    printStream(
      process.stderr,
      prefix: useJson ? '' : 'dartdoc:stderr: ',
      filter: <Pattern>[
        if (!verbose)
          RegExp(
            // Remove warnings from packages outside our control
            r'^ warning: .+: \(.+[\\/]\.pub-cache[\\/]hosted[\\/]pub.dartlang.org[\\/].+\)',
          ),
      ],
    );
    final int exitCode = await process.done;

    if (exitCode != 0) {
      exit(exitCode);
    }

    _sanityCheckDocs();
    checkForUnresolvedDirectives(publishRoot.childDirectory('flutter'));

    _createIndexAndCleanup();

    print('Documentation written to ${publishRoot.path}');
  }

  void _sanityCheckExample(String fileString, String regExpString) {
    final File file = filesystem.file(fileString);
    if (file.existsSync()) {
      final RegExp regExp = RegExp(regExpString, dotAll: true);
      final String contents = file.readAsStringSync();
      if (!regExp.hasMatch(contents)) {
        throw Exception("Missing example code matching '$regExpString' in ${file.path}.");
      }
    } else {
      throw Exception(
          "Missing example code sanity test file ${file.path}. Either it didn't get published, or you might have to update the test to look at a different file.");
    }
  }

  /// A subset of all generated doc files for [_sanityCheckDocs].
  @visibleForTesting
  List<File> get canaries {
    final Directory flutterDirectory = publishRoot.childDirectory('flutter');
    final Directory widgetsDirectory = flutterDirectory.childDirectory('widgets');

    return <File>[
      publishRoot.childDirectory('assets').childFile('overrides.css'),
      flutterDirectory.childDirectory('dart-io').childFile('File-class.html'),
      flutterDirectory.childDirectory('dart-ui').childFile('Canvas-class.html'),
      flutterDirectory.childDirectory('dart-ui').childDirectory('Canvas').childFile('drawRect.html'),
      flutterDirectory
          .childDirectory('flutter_driver')
          .childDirectory('FlutterDriver')
          .childFile('FlutterDriver.connectedTo.html'),
      flutterDirectory
          .childDirectory('flutter_gpu')
          .childFile('flutter_gpu-library.html'),
      flutterDirectory.childDirectory('flutter_test').childDirectory('WidgetTester').childFile('pumpWidget.html'),
      flutterDirectory.childDirectory('material').childFile('Material-class.html'),
      flutterDirectory.childDirectory('material').childFile('Tooltip-class.html'),
      widgetsDirectory.childFile('Widget-class.html'),
      widgetsDirectory.childFile('Listener-class.html'),
    ];
  }

  /// Runs a sanity check by running a test.
  void _sanityCheckDocs([Platform platform = const LocalPlatform()]) {
    for (final File canary in canaries) {
      if (!canary.existsSync()) {
        throw Exception('Missing "${canary.path}", which probably means the documentation failed to build correctly.');
      }
    }
    // Make sure at least one example of each kind includes source code.
    final Directory widgetsDirectory = publishRoot
        .childDirectory('flutter')
        .childDirectory('widgets');

    // Check a "sample" example, any one will do.
    _sanityCheckExample(
      widgetsDirectory.childFile('showGeneralDialog.html').path,
      r'\s*<pre\s+id="longSnippet1".*<code\s+class="language-dart">\s*import &#39;package:flutter&#47;material.dart&#39;;',
    );

    // Check a "snippet" example, any one will do.
    _sanityCheckExample(
      widgetsDirectory.childDirectory('ModalRoute').childFile('barrierColor.html').path,
      r'\s*<pre.*id="sample-code">.*Color\s+get\s+barrierColor.*</pre>',
    );

    // Check a "dartpad" example, any one will do, and check for the correct URL
    // arguments.
    // Just use "main" for any branch other than "stable", just like it is done
    // in the snippet generator at https://github.com/flutter/assets-for-api-docs/blob/cc56972b8f03552fc5f9f9f1ef309efc6c93d7bc/packages/snippets/lib/src/snippet_generator.dart#L104.
    final String? luciBranch = platform.environment['LUCI_BRANCH']?.trim();
    final String expectedChannel = luciBranch == 'stable' ? 'stable' : 'main';
    final List<String> argumentRegExps = <String>[
      r'split=\d+',
      r'run=true',
      r'sample_id=widgets\.Listener\.\d+',
      'channel=$expectedChannel',
    ];
    for (final String argumentRegExp in argumentRegExps) {
      _sanityCheckExample(
        widgetsDirectory.childFile('Listener-class.html').path,
        r'\s*<iframe\s+class="snippet-dartpad"\s+src="'
        r'https:\/\/dartpad.dev\/embed-flutter.html\?.*?\b'
        '$argumentRegExp'
        r'\b.*">\s*<\/iframe>',
      );
    }
  }

  /// Creates a custom index.html because we try to maintain old
  /// paths. Cleanup unused index.html files no longer needed.
  void _createIndexAndCleanup() {
    print('\nCreating a custom index.html in ${publishRoot.childFile('index.html').path}');
    _copyIndexToRootOfDocs();
    _addHtmlBaseToIndex();
    _changePackageToSdkInTitlebar();
    _putRedirectInOldIndexLocation();
    _writeSnippetsIndexFile();
    print('\nDocs ready to go!');
  }

  void _copyIndexToRootOfDocs() {
    publishRoot.childDirectory('flutter').childFile('index.html').copySync(publishRoot.childFile('index.html').path);
  }

  void _changePackageToSdkInTitlebar() {
    final File indexFile = publishRoot.childFile('index.html');
    String indexContents = indexFile.readAsStringSync();
    indexContents = indexContents.replaceFirst(
      '<li><a href="https://flutter.dev">Flutter package</a></li>',
      '<li><a href="https://flutter.dev">Flutter SDK</a></li>',
    );

    indexFile.writeAsStringSync(indexContents);
  }

  void _addHtmlBaseToIndex() {
    final File indexFile = publishRoot.childFile('index.html');
    String indexContents = indexFile.readAsStringSync();
    indexContents = indexContents.replaceFirst(
      '</title>\n',
      '</title>\n  <base href="./flutter/">\n',
    );

    for (final String platform in kPlatformDocs.keys) {
      final String sectionName = kPlatformDocs[platform]!.sectionName;
      final String subdir = kPlatformDocs[platform]!.subdir;
      indexContents = indexContents.replaceAll(
        'href="$sectionName/$sectionName-library.html"',
        'href="../$subdir/index.html"',
      );
    }

    indexFile.writeAsStringSync(indexContents);
  }

  void _putRedirectInOldIndexLocation() {
    const String metaTag = '<meta http-equiv="refresh" content="0;URL=../index.html">';
    publishRoot.childDirectory('flutter').childFile('index.html').writeAsStringSync(metaTag);
  }

  void _writeSnippetsIndexFile() {
    final Directory snippetsDir = publishRoot.childDirectory('snippets');
    if (snippetsDir.existsSync()) {
      const JsonEncoder jsonEncoder = JsonEncoder.withIndent('    ');
      final Iterable<File> files =
          snippetsDir.listSync().whereType<File>().where((File file) => path.extension(file.path) == '.json');
      // Combine all the metadata into a single JSON array.
      final Iterable<String> fileContents = files.map((File file) => file.readAsStringSync());
      final List<dynamic> metadataObjects = fileContents.map<dynamic>(json.decode).toList();
      final String jsonArray = jsonEncoder.convert(metadataObjects);
      snippetsDir.childFile('index.json').writeAsStringSync(jsonArray);
    }
  }
}

/// Downloads and unpacks the platform specific documentation generated by the
/// engine build.
///
/// Unpacks and massages the data so that it can be properly included in the
/// output archive.
class PlatformDocGenerator {
  PlatformDocGenerator({required this.outputDir, required this.filesystem});

  final FileSystem filesystem;
  final Directory outputDir;
  final String engineRevision = FlutterInformation.instance.getEngineRevision();
  final String engineRealm = FlutterInformation.instance.getEngineRealm();

  /// This downloads an archive of platform docs for the engine from the artifact
  /// store and extracts them to the location used for Dartdoc.
  Future<void> generatePlatformDocs() async {
    final String realm = engineRealm.isNotEmpty ? '$engineRealm/' : '';

    for (final String platform in kPlatformDocs.keys) {
      final String zipFile = kPlatformDocs[platform]!.zipName;
      final String url =
          'https://storage.googleapis.com/${realm}flutter_infra_release/flutter/$engineRevision/$zipFile';
      await _extractDocs(url, platform, kPlatformDocs[platform]!, outputDir);
    }
  }

  /// Fetches the zip archive at the specified url.
  ///
  /// Returns null if the archive fails to download after [maxTries] attempts.
  Future<Archive?> _fetchArchive(String url, int maxTries) async {
    List<int>? responseBytes;
    for (int i = 0; i < maxTries; i++) {
      final http.Response response = await http.get(Uri.parse(url));
      if (response.statusCode == 200) {
        responseBytes = response.bodyBytes;
        break;
      }
      stderr.writeln('Failed attempt ${i + 1} to fetch $url.');

      // On failure print a short snipped from the body in case it's helpful.
      final int bodyLength = math.min(1024, response.body.length);
      stderr.writeln('Response status code ${response.statusCode}. Body: ${response.body.substring(0, bodyLength)}');
      sleep(const Duration(seconds: 1));
    }
    return responseBytes == null ? null : ZipDecoder().decodeBytes(responseBytes);
  }

  Future<void> _extractDocs(String url, String name, PlatformDocsSection platform, Directory outputDir) async {
    const int maxTries = 5;
    final Archive? archive = await _fetchArchive(url, maxTries);
    if (archive == null) {
      stderr.writeln('Failed to fetch zip archive from: $url after $maxTries attempts. Giving up.');
      exit(1);
    }

    final Directory output = outputDir.childDirectory(platform.subdir);
    print('Extracting ${platform.zipName} to ${output.path}');
    output.createSync(recursive: true);

    for (final ArchiveFile af in archive) {
      if (!af.name.endsWith('/')) {
        final File file = filesystem.file('${output.path}/${af.name}');
        file.createSync(recursive: true);
        file.writeAsBytesSync(af.content as List<int>);
      }
    }

    final File testFile = output.childFile(platform.checkFile);
    if (!testFile.existsSync()) {
      print('Expected file ${testFile.path} not found');
      exit(1);
    }
    print('${platform.sectionName} ready to go!');
  }
}

/// Recursively copies `srcDir` to `destDir`, invoking [onFileCopied], if
/// specified, for each source/destination file pair.
///
/// Creates `destDir` if needed.
void copyDirectorySync(Directory srcDir, Directory destDir,
    {void Function(File srcFile, File destFile)? onFileCopied, required FileSystem filesystem}) {
  if (!srcDir.existsSync()) {
    throw Exception('Source directory "${srcDir.path}" does not exist, nothing to copy');
  }

  if (!destDir.existsSync()) {
    destDir.createSync(recursive: true);
  }

  for (final FileSystemEntity entity in srcDir.listSync()) {
    final String newPath = path.join(destDir.path, path.basename(entity.path));
    if (entity is File) {
      final File newFile = filesystem.file(newPath);
      entity.copySync(newPath);
      onFileCopied?.call(entity, newFile);
    } else if (entity is Directory) {
      copyDirectorySync(entity, filesystem.directory(newPath), filesystem: filesystem);
    } else {
      throw Exception('${entity.path} is neither File nor Directory');
    }
  }
}

void printStream(Stream<List<int>> stream, {String prefix = '', List<Pattern> filter = const <Pattern>[]}) {
  stream.transform<String>(utf8.decoder).transform<String>(const LineSplitter()).listen((String line) {
    if (!filter.any((Pattern pattern) => line.contains(pattern))) {
      print('$prefix$line'.trim());
    }
  });
}

void zipDirectory(Directory src, File output, {required ProcessManager processManager}) {
  // We would use the archive package to do this in one line, but it
  // is a lot slower, and doesn't do compression nearly as well.
  final ProcessResult zipProcess = processManager.runSync(
    <String>[
      'zip',
      '-r',
      '-9',
      '-q',
      output.path,
      '.',
    ],
    workingDirectory: src.path,
  );

  if (zipProcess.exitCode != 0) {
    print('Creating offline ZIP archive ${output.path} failed:');
    print(zipProcess.stderr);
    exit(1);
  }
}

void tarDirectory(Directory src, File output, {required ProcessManager processManager}) {
  // We would use the archive package to do this in one line, but it
  // is a lot slower, and doesn't do compression nearly as well.
  final ProcessResult tarProcess = processManager.runSync(
    <String>[
      'tar',
      'cf',
      output.path,
      '--use-compress-program',
      'gzip --best',
      'flutter.docset',
    ],
    workingDirectory: src.path,
  );

  if (tarProcess.exitCode != 0) {
    print('Creating a tarball ${output.path} failed:');
    print(tarProcess.stderr);
    exit(1);
  }
}

Future<Process> runPubProcess({
  required List<String> arguments,
  Directory? workingDirectory,
  Map<String, String>? environment,
  @visibleForTesting ProcessManager processManager = const LocalProcessManager(),
  @visibleForTesting FileSystem filesystem = const LocalFileSystem(),
}) {
  return processManager.start(
    <Object>[FlutterInformation.instance.getFlutterBinaryPath().path, 'pub', ...arguments],
    workingDirectory: (workingDirectory ?? filesystem.currentDirectory).path,
    environment: environment,
  );
}

List<String> findPackageNames(FileSystem filesystem) {
  return findPackages(filesystem).map<String>((FileSystemEntity file) => path.basename(file.path)).toList();
}

/// Finds all packages in the Flutter SDK
List<Directory> findPackages(FileSystem filesystem) {
  return FlutterInformation.instance
      .getFlutterRoot()
      .childDirectory('packages')
      .listSync()
      .where((FileSystemEntity entity) {
        if (entity is! Directory) {
          return false;
        }
        final File pubspec = entity.childFile('pubspec.yaml');
        if (!pubspec.existsSync()) {
          print("Unexpected package '${entity.path}' found in packages directory");
          return false;
        }
        // Would be nice to use a real YAML parser here, but we don't want to
        // depend on a whole package for it, and this is sufficient.
        return !pubspec.readAsStringSync().contains('nodoc: true');
      })
      .cast<Directory>()
      .toList();
}

/// An exception class used to indicate problems when collecting information.
class FlutterInformationException implements Exception {
  FlutterInformationException(this.message);
  final String message;

  @override
  String toString() {
    return '$runtimeType: $message';
  }
}

/// A singleton used to consolidate the way in which information about the
/// Flutter repo and environment is collected.
///
/// Collects the information once, and caches it for any later access.
///
/// The singleton instance can be overridden by tests by setting [instance].
class FlutterInformation {
  FlutterInformation({
    this.platform = const LocalPlatform(),
    this.processManager = const LocalProcessManager(),
    this.filesystem = const LocalFileSystem(),
  });

  final Platform platform;
  final ProcessManager processManager;
  final FileSystem filesystem;

  static FlutterInformation? _instance;

  static FlutterInformation get instance => _instance ??= FlutterInformation();

  @visibleForTesting
  static set instance(FlutterInformation? value) => _instance = value;

  /// The path to the Dart binary in the Flutter repo.
  ///
  /// This is probably a shell script.
  File getFlutterBinaryPath() {
    return getFlutterRoot().childDirectory('bin').childFile('flutter');
  }

  /// The path to the Flutter repo root directory.
  ///
  /// If the environment variable `FLUTTER_ROOT` is set, will use that instead
  /// of looking for it.
  ///
  /// Otherwise, uses the output of `flutter --version --machine` to find the
  /// Flutter root.
  Directory getFlutterRoot() {
    if (platform.environment['FLUTTER_ROOT'] != null) {
      return filesystem.directory(platform.environment['FLUTTER_ROOT']);
    }
    return getFlutterInformation()['flutterRoot']! as Directory;
  }

  /// Gets the semver version of the Flutter framework in the repo.
  Version getFlutterVersion() => getFlutterInformation()['frameworkVersion']! as Version;

  /// Gets the git hash of the engine used by the Flutter framework in the repo.
  String getEngineRevision() => getFlutterInformation()['engineRevision']! as String;

  /// Gets the value stored in bin/internal/engine.realm used by the Flutter
  /// framework repo.
  String getEngineRealm() => getFlutterInformation()['engineRealm']! as String;

  /// Gets the git hash of the Flutter framework in the repo.
  String getFlutterRevision() => getFlutterInformation()['flutterGitRevision']! as String;

  /// Gets the name of the current branch in the Flutter framework in the repo.
  String getBranchName() => getFlutterInformation()['branchName']! as String;

  Map<String, Object>? _cachedFlutterInformation;

  /// Gets a Map of various kinds of information about the Flutter repo.
  Map<String, Object> getFlutterInformation() {
    if (_cachedFlutterInformation != null) {
      return _cachedFlutterInformation!;
    }

    String flutterVersionJson;
    if (platform.environment['FLUTTER_VERSION'] != null) {
      flutterVersionJson = platform.environment['FLUTTER_VERSION']!;
    } else {
      // Determine which flutter command to run, which will determine which
      // flutter root is eventually used. If the FLUTTER_ROOT is set, then use
      // that flutter command, otherwise use the first one in the PATH.
      String flutterCommand;
      if (platform.environment['FLUTTER_ROOT'] != null) {
        flutterCommand = filesystem
            .directory(platform.environment['FLUTTER_ROOT'])
            .childDirectory('bin')
            .childFile('flutter')
            .absolute
            .path;
      } else {
        flutterCommand = 'flutter';
      }
      ProcessResult result;
      try {
        result = processManager.runSync(
          <String>[flutterCommand, '--version', '--machine'],
          stdoutEncoding: utf8,
        );
      } on ProcessException catch (e) {
        throw FlutterInformationException(
            'Unable to determine Flutter information. Either set FLUTTER_ROOT, or place the '
            'flutter command in your PATH.\n$e');
      }
      if (result.exitCode != 0) {
        throw FlutterInformationException(
            'Unable to determine Flutter information, because of abnormal exit of flutter command.');
      }
      // Strip out any non-JSON that might be printed along with the command
      // output.
      flutterVersionJson = (result.stdout as String)
          .replaceAll('Waiting for another flutter command to release the startup lock...', '');
    }

    final Map<String, dynamic> flutterVersion = json.decode(flutterVersionJson) as Map<String, dynamic>;
    if (flutterVersion['flutterRoot'] == null ||
        flutterVersion['frameworkVersion'] == null ||
        flutterVersion['dartSdkVersion'] == null) {
      throw FlutterInformationException(
          'Flutter command output has unexpected format, unable to determine flutter root location.');
    }

    final Map<String, Object> info = <String, Object>{};
    final Directory flutterRoot = filesystem.directory(flutterVersion['flutterRoot']! as String);
    info['flutterRoot'] = flutterRoot;
    info['frameworkVersion'] = Version.parse(flutterVersion['frameworkVersion'] as String);
    info['engineRevision'] = flutterVersion['engineRevision'] as String;
    final File engineRealm = flutterRoot.childDirectory('bin').childDirectory('internal').childFile('engine.realm');
    info['engineRealm'] = engineRealm.existsSync() ? engineRealm.readAsStringSync().trim() : '';

    final RegExpMatch? dartVersionRegex = RegExp(r'(?<base>[\d.]+)(?:\s+\(build (?<detail>[-.\w]+)\))?')
        .firstMatch(flutterVersion['dartSdkVersion'] as String);
    if (dartVersionRegex == null) {
      throw FlutterInformationException(
          'Flutter command output has unexpected format, unable to parse dart SDK version ${flutterVersion['dartSdkVersion']}.');
    }
    info['dartSdkVersion'] =
        Version.parse(dartVersionRegex.namedGroup('detail') ?? dartVersionRegex.namedGroup('base')!);

    info['branchName'] = _getBranchName();
    info['flutterGitRevision'] = _getFlutterGitRevision();
    _cachedFlutterInformation = info;

    return info;
  }

  // Get the name of the release branch.
  //
  // On LUCI builds, the git HEAD is detached, so first check for the env
  // variable "LUCI_BRANCH"; if it is not set, fall back to calling git.
  String _getBranchName() {
    final String? luciBranch = platform.environment['LUCI_BRANCH'];
    if (luciBranch != null && luciBranch.trim().isNotEmpty) {
      return luciBranch.trim();
    }
    final ProcessResult gitResult = processManager.runSync(<String>['git', 'status', '-b', '--porcelain']);
    if (gitResult.exitCode != 0) {
      throw 'git status exit with non-zero exit code: ${gitResult.exitCode}';
    }
    final RegExp gitBranchRegexp = RegExp(r'^## (.*)');
    final RegExpMatch? gitBranchMatch =
        gitBranchRegexp.firstMatch((gitResult.stdout as String).trim().split('\n').first);
    return gitBranchMatch == null ? '' : gitBranchMatch.group(1)!.split('...').first;
  }

  // Get the git revision for the repo.
  String _getFlutterGitRevision() {
    const int kGitRevisionLength = 10;

    final ProcessResult gitResult = processManager.runSync(<String>['git', 'rev-parse', 'HEAD']);
    if (gitResult.exitCode != 0) {
      throw 'git rev-parse exit with non-zero exit code: ${gitResult.exitCode}';
    }
    final String gitRevision = (gitResult.stdout as String).trim();

    return gitRevision.length > kGitRevisionLength ? gitRevision.substring(0, kGitRevisionLength) : gitRevision;
  }
}
