// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

import 'dart:async';
import 'dart:io';

import 'package:analyzer/src/lint/registry.dart';
import 'package:github/github.dart';
import 'package:http/http.dart' as http;
import 'package:linter/src/analyzer.dart';
import 'package:linter/src/rules.dart';
import 'package:linter/src/util/score_utils.dart' as score_utils;
import 'package:linter/src/utils.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:yaml/yaml.dart';

/// todo (pq): reign in the nullable types

const _allPathSuffix = '/example/all.yaml';

/// We don't care about SDKs previous to this bottom.
final Version bottomDartSdk = Version(2, 0, 0);
final Map<String, String?> _dartSdkToLinterMap = <String, String?>{};

final _flutterOptionsUrl = Uri.https('raw.githubusercontent.com',
    '/flutter/packages/main/packages/flutter_lints/lib/flutter.yaml');
final _flutterRepoOptionsUrl = Uri.https(
    'raw.githubusercontent.com', '/flutter/flutter/main/analysis_options.yaml');

List<String>? _flutterRepoRules;

List<String>? _flutterRules;

int? _latestMinor;
Iterable<LintRule>? _registeredLints;
final _repoPathPrefix =
    Uri.https('raw.githubusercontent.com', '/dart-lang/linter/');

List<String>? _sdkTags;

List<String>? _linterTags;

Map<String, List<String?>> _sinceMap = <String, List<String>>{};

Future<List<String>> get flutterRepoRules async =>
    _flutterRepoRules ??= await score_utils.fetchRules(_flutterRepoOptionsUrl);

Future<List<String>> get flutterRules async =>
    _flutterRules ??= await score_utils.fetchRules(_flutterOptionsUrl);

Future<int> get latestMinor async =>
    _latestMinor ??= await _readLatestMinorVersion();

Iterable<LintRule> get registeredLints {
  if (_registeredLints == null) {
    registerLintRules();
    _registeredLints = Registry.ruleRegistry;
  }
  return _registeredLints!;
}

Future<String?> dartSdkForLinter(String version, Authentication? auth) async {
  var sdkVersions = <String>[];
  var sdks = await getSdkTags(auth);
  for (var sdk in sdks) {
    var linterVersion = await linterForDartSdk(sdk);
    if (linterVersion == version) {
      sdkVersions.add(sdk);
    }
  }

  sdkVersions.sort();
  return sdkVersions.isNotEmpty ? sdkVersions.first : null;
}

Future<List<String>> fetchRulesForVersion(String version) async =>
    score_utils.fetchRules(_repoPathPrefix.resolve('$version$_allPathSuffix'));

Future<String?> findSinceDartSdk(String linterVersion,
        {Authentication? auth}) async =>
    await dartSdkForLinter(linterVersion, auth);

Future<String?> findSinceLinter(String lint, [Authentication? auth]) async {
  var linterReleases = await getLinterReleases(auth);

  for (var version in linterReleases) {
    var rules = await rulesForVersion(version);
    if (rules != null) {
      if (rules.contains(lint)) {
        return version;
      }
    }
  }

  return null;
}

Future<List<String>> getSdkTags(Authentication? auth,
        {bool onlyStable = false}) async =>
    _sdkTags ??= await _fetchSdkTags(auth, onlyStable: onlyStable);

Future<List<String>> getLinterReleases([Authentication? auth]) async =>
    _linterTags ??=
        (await _fetchLinterReleaseTags(auth)).reversed.toList(growable: false);

Future<String?> linterForDartSdk(String sdk) async =>
    _dartSdkToLinterMap[sdk] ??= await _fetchLinterForVersion(sdk);

Future<List<String?>?> rulesForVersion(String version) async =>
    _sinceMap[version] ??= await fetchRulesForVersion(version);

Future<String> _fetchDEPSforVersion(String version) async {
  var client = http.Client();
  //https://raw.githubusercontent.com/dart-lang/sdk/2.1.0-dev.1.0/DEPS
  var req = await client.get(
      Uri.https('raw.githubusercontent.com', '/dart-lang/sdk/$version/DEPS'));
  return req.body;
}

final _linterReleasePattern = RegExp(r'\d+\.\d+(\.\d+)');

Future<String?> _commitReferenceToVersion(String version) async {
  if (_linterReleasePattern.hasMatch(version)) {
    return version;
  }

  // Get all tags which include this commit reference
  var result = await Process.run('git', ['tag', '--contains', version]);
  var output = result.stdout;
  if (output is String) {
    var tags = _linterReleasePattern.allMatches(output);
    // If commit is contained by a linter tag
    if (tags.isNotEmpty) {
      // Take the earliest (first) release which includes this commit
      var latestTag = tags.first.group(0);
      if (latestTag != null) {
        return latestTag;
      }
    }
  }

  return null;
}

Future<String?> _fetchLinterForVersion(String version) async {
  var deps = await _fetchDEPSforVersion(version);
  for (var untrimmedLine in deps.split('\n')) {
    var line = untrimmedLine.trim();
    if (line.startsWith('"linter')) {
      // "linter_tag": "0.1.59",
      var oldSplit = line.split('"linter_tag":');
      if (oldSplit.length == 2) {
        //  "0.1.59",
        return _commitReferenceToVersion(oldSplit[1].split('"')[1]);
      }

      // "linter_rev": "f2c55484e8ebda0aec8c2fea637b3bd5b17258ca",
      var newSplit = line.split('"linter_rev":');
      if (newSplit.length == 2) {
        // "f2c55484e8ebda0aec8c2fea637b3bd5b17258ca",
        var parsedLinterVersion = newSplit[1].split('"')[1];
        return _commitReferenceToVersion(parsedLinterVersion);
      }
    }
  }
  return null;
}

final _releaseTagPattern = RegExp(r'\d+');
final _stableReleasePattern = RegExp(r'^\d+\.\d+\.\d+$');

Future<List<String>> _fetchLinterReleaseTags(Authentication? auth) async =>
    await _fetchRepoTags(
        'dart-lang', 'linter', auth, _stableReleasePattern.hasMatch);

Future<List<String>> _fetchSdkTags(Authentication? auth,
        {bool onlyStable = false}) async =>
    await _fetchRepoTags('dart-lang', 'sdk', auth, (t) {
      // Filter on numeric release tags.
      if (!t.startsWith(_releaseTagPattern)) {
        return false;
      }

      // Filter on bottom.
      try {
        var version = Version.parse(t);
        if (version < bottomDartSdk) {
          return false;
        }
      } on FormatException {
        return false;
      }

      if (onlyStable) {
        if (!_stableReleasePattern.hasMatch(t)) {
          return false;
        }
      }

      return true;
    });

Future<List<String>> _fetchRepoTags(String org, String repo,
    Authentication? auth, bool Function(String) where) async {
  var github = GitHub(auth: auth);
  var slug = RepositorySlug(org, repo);

  printToConsole('list repository tags: $slug');
  printToConsole(
      'authentication:  ${auth != null ? "(token)" : "(anonymous)"}');

  var tags = await github.repositories
      .listTags(slug)
      .map((t) => t.name)
      .toList()
      .catchError((e) {
    printToConsole('exception caught fetching $repo tags');
    printToConsole(e);
    printToConsole('(using cached $repo values)');
    return Future.value(<String>[]);
  });

  return tags.whereType<String>().where(where).toList(growable: false);
}

Future<int> _readLatestMinorVersion() async {
  var contents = await File('pubspec.yaml').readAsString();
  var pubspec = loadYamlNode(contents) as YamlMap;
  var version = pubspec['version'] as String;
  // 1.15.0
  return int.parse(version.split('.')[1]);
}
