// Copyright (c) 2012, 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 'package:pub_semver/pub_semver.dart';

import '../exceptions.dart';
import '../log.dart' as log;
import '../package_name.dart';
import '../sdk.dart';
import '../source/hosted.dart';
import '../source/path.dart';
import '../source/sdk.dart';
import '../validator.dart';

/// A validator that validates a package's dependencies.
class DependencyValidator extends Validator {
  @override
  Future validate() async {
    /// Whether any dependency has a caret constraint.
    var hasCaretDep = false;

    /// Emit an error for dependencies from unknown SDKs or without appropriate
    /// constraints on the Dart SDK.
    void warnAboutSdkSource(PackageRange dep) {
      final identifier = (dep.description as SdkDescription).sdk;
      final sdk = sdks[identifier];
      if (sdk == null) {
        errors.add('Unknown SDK "$identifier" for dependency "${dep.name}".');
        return;
      }
    }

    /// Warn that dependencies should use the hosted source.
    Future warnAboutSource(PackageRange dep) async {
      List<Version> versions;
      try {
        final ids = await cache.getVersions(cache.hosted.refFor(dep.name));
        versions = ids.map((id) => id.version).toList();
      } on ApplicationException catch (_) {
        versions = [];
      }

      String constraint;
      if (versions.isNotEmpty) {
        constraint = '^${Version.primary(versions)}';
      } else {
        constraint = dep.constraint.toString();
        if (!dep.constraint.isAny && dep.constraint is! Version) {
          constraint = '"$constraint"';
        }
      }

      // Path sources are errors. Other sources are just warnings.
      final messages = dep.source is PathSource ? errors : warnings;

      messages.add('Don\'t depend on "${dep.name}" from the ${dep.source} '
          'source. Use the hosted source instead. For example:\n'
          '\n'
          'dependencies:\n'
          '  ${dep.name}: $constraint\n'
          '\n'
          'Using the hosted source ensures that everyone can download your '
          'package\'s dependencies along with your package.');
    }

    /// Warn about improper dependencies on Flutter.
    void warnAboutFlutterSdk(PackageRange dep) {
      if (dep.source is SdkSource) {
        warnAboutSdkSource(dep);
        return;
      }

      errors.add('Don\'t depend on "${dep.name}" from the ${dep.source} '
          'source. Use the SDK source instead. For example:\n'
          '\n'
          'dependencies:\n'
          '  ${dep.name}:\n'
          '    sdk: ${dep.constraint}\n'
          '\n'
          'The Flutter SDK is downloaded and managed outside of pub.');
    }

    /// Warn that dependencies should have version constraints.
    void warnAboutNoConstraint(PackageRange dep) {
      var message = 'Your dependency on "${dep.name}" should have a version '
          'constraint.';
      final locked = context.entrypoint.lockFile.packages[dep.name];
      if (locked != null) {
        message = '$message For example:\n'
            '\n'
            'dependencies:\n'
            '  ${dep.name}: ^${locked.version}\n';
      }
      warnings.add('$message\n'
          'Without a constraint, you\'re promising to support ${log.bold("all")} '
          'future versions of "${dep.name}".');
    }

    /// Warn that dependencies should allow more than a single version.
    void warnAboutSingleVersionConstraint(PackageRange dep) {
      warnings.add(
          'Your dependency on "${dep.name}" should allow more than one version. '
          'For example:\n'
          '\n'
          'dependencies:\n'
          '  ${dep.name}: ^${dep.constraint}\n'
          '\n'
          'Constraints that are too tight will make it difficult for people to '
          'use your package\n'
          'along with other packages that also depend on "${dep.name}".');
    }

    /// Warn that dependencies should have lower bounds on their constraints.
    void warnAboutNoConstraintLowerBound(PackageRange dep) {
      var message =
          'Your dependency on "${dep.name}" should have a lower bound.';
      final locked = context.entrypoint.lockFile.packages[dep.name];
      if (locked != null) {
        String constraint;
        if (locked.version == (dep.constraint as VersionRange).max) {
          constraint = '^${locked.version}';
        } else {
          constraint = '">=${locked.version} ${dep.constraint}"';
        }

        message = '$message For example:\n'
            '\n'
            'dependencies:\n'
            '  ${dep.name}: $constraint\n';
      }
      warnings.add('$message\n'
          'Without a constraint, you\'re promising to support ${log.bold("all")} '
          'previous versions of "${dep.name}".');
    }

    /// Warn that dependencies should have upper bounds on their constraints.
    void warnAboutNoConstraintUpperBound(PackageRange dep) {
      String constraint;
      if ((dep.constraint as VersionRange).includeMin) {
        constraint = '^${(dep.constraint as VersionRange).min}';
      } else {
        constraint = '"${dep.constraint} '
            '<${(dep.constraint as VersionRange).min!.nextBreaking}"';
      }
      // TODO: Handle the case where `dep.constraint.min` is null.

      warnings.add(
          'Your dependency on "${dep.name}" should have an upper bound. For '
          'example:\n'
          '\n'
          'dependencies:\n'
          '  ${dep.name}: $constraint\n'
          '\n'
          'Without an upper bound, you\'re promising to support '
          '${log.bold("all")} future versions of ${dep.name}.');
    }

    void warnAboutPrerelease(String dependencyName, VersionRange constraint) {
      final packageVersion = package.version;
      if (constraint.min != null &&
          constraint.min!.isPreRelease &&
          !packageVersion.isPreRelease) {
        warnings.add('Packages dependent on a pre-release of another package '
            'should themselves be published as a pre-release version. '
            'If this package needs $dependencyName version ${constraint.min}, '
            'consider publishing the package as a pre-release instead.\n'
            'See https://dart.dev/tools/pub/publishing#publishing-prereleases '
            'For more information on pre-releases.');
      }
    }

    /// Validates all dependencies in [dependencies].
    Future validateDependencies(Iterable<PackageRange> dependencies) async {
      for (var dependency in dependencies) {
        final constraint = dependency.constraint;
        if (dependency.name == 'flutter') {
          warnAboutFlutterSdk(dependency);
        } else if (dependency.source is SdkSource) {
          warnAboutSdkSource(dependency);
        } else if (dependency.source is! HostedSource) {
          await warnAboutSource(dependency);
        } else {
          if (constraint.isAny) {
            warnAboutNoConstraint(dependency);
          } else if (constraint is VersionRange) {
            if (constraint is Version) {
              warnAboutSingleVersionConstraint(dependency);
            } else {
              warnAboutPrerelease(dependency.name, constraint);
              if (constraint.min == null) {
                warnAboutNoConstraintLowerBound(dependency);
              } else if (constraint.max == null) {
                warnAboutNoConstraintUpperBound(dependency);
              }
            }
            hasCaretDep = hasCaretDep || constraint.toString().startsWith('^');
          }
        }
      }
    }

    await validateDependencies(package.pubspec.dependencies.values);
  }
}
