// 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);
  }
}
