// 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:convert/convert.dart';
import 'package:file/file.dart';
import 'package:file/local.dart';
import 'package:http/http.dart' as http;
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(
    publishRoot: publishRoot,
    packageRoot: packageRoot,
    docsRoot: docsRoot,
    filesystem: filesystem,
    processManager: processManager,
    platform: platform,
  );
  configurator.generateConfiguration();

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

  final 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 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 pubspec = <String>[
      'name: $kDummyPackageName',
      'homepage: https://flutter.dev',
      'version: 0.0.0',
      'environment:',
      "  sdk: '^${FlutterInformation.instance.getDartSdkVersion()}'",
      '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 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 = FixedDateTimeFormatter('YYYY-MM-DD hh:mm').encode(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 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 files = <String>['README.md', 'analysis_options.yaml', 'dartdoc_options.yaml'];
    for (final 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, LUCI 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 result = ProcessWrapper(
      await processManager.start(<String>[
        'dashing',
        'build',
        '--source',
        publishRoot.path,
        '--config',
        docsRoot.childFile('dashing.json').path,
      ], workingDirectory: packageRoot.path),
    );
    final 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 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 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 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.
    var 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 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 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 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(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 expectedChannel = luciBranch == 'stable' ? 'stable' : 'main';
    final argumentRegExps = <String>[
      r'split=\d+',
      r'run=true',
      r'sample_id=widgets\.Listener\.\d+',
      'channel=$expectedChannel',
    ];
    for (final argumentRegExp in argumentRegExps) {
      _sanityCheckExample(
        widgetsDirectory.childFile('Listener-class.html').path,
        r'\s*<iframe\s+class="snippet-dartpad"\s+allow="clipboard-write"\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 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.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 realm = engineRealm.isNotEmpty ? '$engineRealm/' : '';

    for (final String platform in kPlatformDocs.keys) {
      final String zipFile = kPlatformDocs[platform]!.zipName;
      final 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 (var 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 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;

  /// Gets the current Dart SDK version.
  Version getDartSdkVersion() => getFlutterInformation()['dartSdkVersion']! as Version;

  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 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 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('cache')
        .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 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 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;
  }
}
