// 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 [stripLowerBound] 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 the directory of [receivingPackage].
///
/// The syntax used for hosted will depend on the language version of
/// [receivingPackage].
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(),
    };
  }
}
