content: // Copyright 2021 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'dart:convert';
  
  import 'package:grinder/grinder.dart';
  import 'package:http/http.dart' as http;
  
  import 'utils.dart';
  
  @Task('Download Bootstrap 5.x for testing purposes.')
  Future<void> fetchBootstrap5() => _getLatestRelease('twbs/bootstrap');
  
  @Task('Download Bootstrap 4.x for testing purposes.')
  Future<void> fetchBootstrap4() =>
      _getLatestRelease('twbs/bootstrap', pattern: RegExp(r'^v4\.'));
  
  @Task('Download Bourbon for testing purposes.')
  Future<void> fetchBourbon() => _getLatestRelease('thoughtbot/bourbon');
  
  @Task('Download Foundation for testing purposes.')
  Future<void> fetchFoundation() =>
      _getLatestRelease('foundation/foundation-sites');
  
  @Task('Download Bulma for testing purposes.')
  Future<void> fetchBulma() => _getLatestRelease('jgthms/bulma');
  
  /// Clones the latest release of the given GitHub repository [slug].
  ///
  /// If [pattern] is passed, this will clone the latest release that matches that
  /// pattern.
  Future<void> _getLatestRelease(String slug, {Pattern? pattern}) async {
    cloneOrCheckout(
      'https://github.com/$slug',
      await _findLatestRelease(slug, pattern: pattern),
    );
  }
  
  /// Returns the tag name of the latest release for the given GitHub repository
  /// [slug].
  ///
  /// If [pattern] is passed, this will find the latest release that matches that
  /// pattern.
  Future<String> _findLatestRelease(String slug, {Pattern? pattern}) async {
    var releases = await _fetchReleases(slug);
    if (pattern == null) return releases[0]['tag_name'] as String;
  
    var page = 1;
    while (releases.isNotEmpty) {
      for (var {'tag_name': String tagName} in releases) {
        if (pattern.allMatches(tagName).isNotEmpty) return tagName;
      }
  
      page++;
      releases = await _fetchReleases(slug, page: page);
    }
  
    fail("Couldn't find a release of $slug matching $pattern.");
  }
  
  /// Fetches the GitHub releases page for the repo at [slug].
  Future<List<Map<String, dynamic>>> _fetchReleases(
    String slug, {
    int page = 1,
  }) async {
    var result = json.decode(
      await http.read(
        Uri.parse(
          "https://api.github.com/repos/$slug/releases?page=$page",
        ),
        headers: {
          "accept": "application/vnd.github.v3+json",
          "authorization": githubAuthorization,
        },
      ),
    ) as List<dynamic>;
    return result.cast<Map<String, dynamic>>();
  }
  