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

import 'package.dart';
import 'package_name.dart';
import 'pubspec.dart';
import 'source/hosted.dart';
import 'system_cache.dart';

/// Returns a new [Pubspec] without [original]'s dev_dependencies.
Pubspec stripDevDependencies(Pubspec original) {
  return original.copyWith(devDependencies: []);
}

/// Returns a new [Pubspec] without [original]'s dependency_overrides.
Pubspec stripDependencyOverrides(Pubspec original) {
  return original.copyWith(dependencyOverrides: []);
}

/// Returns new pubspec with the same dependencies as [original] but with the
/// the bounds of the constraints removed.
///
/// If [stripLower] is `false` (the default) only the upper bound is removed.
///
/// If [stripOnly] is provided, only the packages whose names are in [stripOnly]
/// will have their bounds removed. If [stripOnly] is not specified or empty,
/// then all packages will have their bounds removed.
Pubspec stripVersionBounds(
  Pubspec original, {
  Iterable<String>? stripOnly,
  bool stripLowerBound = false,
}) {
  stripOnly ??= [];

  List<PackageRange> stripBounds(
    Map<String, PackageRange> constrained,
  ) {
    final result = <PackageRange>[];

    for (final name in constrained.keys) {
      final packageRange = constrained[name]!;
      var unconstrainedRange = packageRange;

      if (stripOnly!.isEmpty || stripOnly.contains(packageRange.name)) {
        unconstrainedRange = PackageRange(
          packageRange.toRef(),
          stripLowerBound
              ? VersionConstraint.any
              : stripUpperBound(packageRange.constraint),
        );
      }
      result.add(unconstrainedRange);
    }

    return result;
  }

  return original.copyWith(
    dependencies: stripBounds(original.dependencies),
    devDependencies: stripBounds(original.devDependencies),
  );
}

/// Returns a pubspec with the same dependencies as [original] but with all
/// version constraints replaced by `>=c` where `c`, is the member of `current`
/// that has same name as the dependency.
Pubspec atLeastCurrent(Pubspec original, List<PackageId> current) {
  List<PackageRange> fixBounds(
    Map<String, PackageRange> constrained,
  ) {
    final result = <PackageRange>[];

    for (final name in constrained.keys) {
      final packageRange = constrained[name]!;
      final currentVersion = current.firstWhereOrNull((id) => id.name == name);
      if (currentVersion == null) {
        result.add(packageRange);
      } else {
        result.add(
          packageRange.toRef().withConstraint(
                VersionRange(min: currentVersion.version, includeMin: true),
              ),
        );
      }
    }

    return result;
  }

  return original.copyWith(
    dependencies: fixBounds(original.dependencies),
    devDependencies: fixBounds(original.devDependencies),
  );
}

/// Removes the upper bound of [constraint]. If [constraint] is the
/// empty version constraint, [VersionConstraint.empty] will be returned.
VersionConstraint stripUpperBound(VersionConstraint constraint) {
  ArgumentError.checkNotNull(constraint, 'constraint');

  /// A [VersionConstraint] has to either be a [VersionRange], [VersionUnion],
  /// or the empty [VersionConstraint].
  if (constraint is VersionRange) {
    return VersionRange(min: constraint.min, includeMin: constraint.includeMin);
  }

  if (constraint is VersionUnion) {
    if (constraint.ranges.isEmpty) return VersionConstraint.empty;

    final firstRange = constraint.ranges.first;
    return VersionRange(min: firstRange.min, includeMin: firstRange.includeMin);
  }

  assert(constraint == VersionConstraint.empty, 'unknown constraint type');

  /// If it gets here, [constraint] is the empty version constraint, so we
  /// just return an empty version constraint.
  return VersionConstraint.empty;
}

/// Returns a somewhat normalized version the description of a dependency with a
/// version constraint (what comes after the version name in a dependencies
/// section) as a json-style object.
///
/// Will use just the constraint for dependencies hosted at the default host.
///
/// Relative paths will be relative to [relativeEntrypoint].
///
/// The syntax used for hosted will depend on the language version of
/// [relativeEntrypoint]
Object pubspecDescription(
  PackageRange range,
  SystemCache cache,
  Package receivingPackage,
) {
  final description = range.description;

  final constraint = range.constraint;
  if (description is HostedDescription &&
      description.url == cache.hosted.defaultUrl) {
    return constraint.toString();
  } else {
    return {
      range.source.name: description.serializeForPubspec(
        containingDir: receivingPackage.dir,
        languageVersion: receivingPackage.pubspec.languageVersion,
      ),
      if (!constraint.isAny) 'version': constraint.toString(),
    };
  }
}
