// Copyright (c) 2014, 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 'utils.dart';
import 'version.dart';
import 'version_constraint.dart';
import 'version_union.dart';

/// Constrains versions to a fall within a given range.
///
/// If there is a minimum, then this only allows versions that are at that
/// minimum or greater. If there is a maximum, then only versions less than
/// that are allowed. In other words, this allows `>= min, < max`.
///
/// Version ranges are ordered first by their lower bounds, then by their upper
/// bounds. For example, `>=1.0.0 <2.0.0` is before `>=1.5.0 <2.0.0` is before
/// `>=1.5.0 <3.0.0`.
class VersionRange implements Comparable<VersionRange>, VersionConstraint {
  /// The minimum end of the range.
  ///
  /// If [includeMin] is `true`, this will be the minimum allowed version.
  /// Otherwise, it will be the highest version below the range that is not
  /// allowed.
  ///
  /// This may be `null` in which case the range has no minimum end and allows
  /// any version less than the maximum.
  final Version min;

  /// The maximum end of the range.
  ///
  /// If [includeMax] is `true`, this will be the maximum allowed version.
  /// Otherwise, it will be the lowest version above the range that is not
  /// allowed.
  ///
  /// This may be `null` in which case the range has no maximum end and allows
  /// any version greater than the minimum.
  final Version max;

  /// If `true` then [min] is allowed by the range.
  final bool includeMin;

  /// If `true`, then [max] is allowed by the range.
  final bool includeMax;

  /// Creates a new version range from [min] to [max], either inclusive or
  /// exclusive.
  ///
  /// If it is an error if [min] is greater than [max].
  ///
  /// Either [max] or [min] may be omitted to not clamp the range at that end.
  /// If both are omitted, the range allows all versions.
  ///
  /// If [includeMin] is `true`, then the minimum end of the range is inclusive.
  /// Likewise, passing [includeMax] as `true` makes the upper end inclusive.
  ///
  /// If [alwaysIncludeMaxPreRelease] is `true`, this will always include
  /// pre-release versions of an exclusive [max]. Otherwise, it will use the
  /// default behavior for pre-release versions of [max].
  factory VersionRange(
      {Version min,
      Version max,
      bool includeMin = false,
      bool includeMax = false,
      bool alwaysIncludeMaxPreRelease = false}) {
    if (min != null && max != null && min > max) {
      throw ArgumentError(
          'Minimum version ("$min") must be less than maximum ("$max").');
    }

    if (!alwaysIncludeMaxPreRelease &&
        !includeMax &&
        max != null &&
        !max.isPreRelease &&
        max.build.isEmpty &&
        (min == null ||
            !min.isPreRelease ||
            !equalsWithoutPreRelease(min, max))) {
      max = max.firstPreRelease;
    }

    return VersionRange._(min, max, includeMin, includeMax);
  }

  VersionRange._(this.min, this.max, this.includeMin, this.includeMax);

  @override
  bool operator ==(other) {
    if (other is! VersionRange) return false;

    return min == other.min &&
        max == other.max &&
        includeMin == other.includeMin &&
        includeMax == other.includeMax;
  }

  @override
  int get hashCode =>
      min.hashCode ^
      (max.hashCode * 3) ^
      (includeMin.hashCode * 5) ^
      (includeMax.hashCode * 7);

  @override
  bool get isEmpty => false;

  @override
  bool get isAny => min == null && max == null;

  /// Tests if [other] falls within this version range.
  @override
  bool allows(Version other) {
    if (min != null) {
      if (other < min) return false;
      if (!includeMin && other == min) return false;
    }

    if (max != null) {
      if (other > max) return false;
      if (!includeMax && other == max) return false;
    }

    return true;
  }

  @override
  bool allowsAll(VersionConstraint other) {
    if (other.isEmpty) return true;
    if (other is Version) return allows(other);

    if (other is VersionUnion) {
      return other.ranges.every(allowsAll);
    }

    if (other is VersionRange) {
      return !allowsLower(other, this) && !allowsHigher(other, this);
    }

    throw ArgumentError('Unknown VersionConstraint type $other.');
  }

  @override
  bool allowsAny(VersionConstraint other) {
    if (other.isEmpty) return false;
    if (other is Version) return allows(other);

    if (other is VersionUnion) {
      return other.ranges.any(allowsAny);
    }

    if (other is VersionRange) {
      return !strictlyLower(other, this) && !strictlyHigher(other, this);
    }

    throw ArgumentError('Unknown VersionConstraint type $other.');
  }

  @override
  VersionConstraint intersect(VersionConstraint other) {
    if (other.isEmpty) return other;
    if (other is VersionUnion) return other.intersect(this);

    // A range and a Version just yields the version if it's in the range.
    if (other is Version) {
      return allows(other) ? other : VersionConstraint.empty;
    }

    if (other is VersionRange) {
      // Intersect the two ranges.
      Version intersectMin;
      bool intersectIncludeMin;
      if (allowsLower(this, other)) {
        if (strictlyLower(this, other)) return VersionConstraint.empty;
        intersectMin = other.min;
        intersectIncludeMin = other.includeMin;
      } else {
        if (strictlyLower(other, this)) return VersionConstraint.empty;
        intersectMin = min;
        intersectIncludeMin = includeMin;
      }

      Version intersectMax;
      bool intersectIncludeMax;
      if (allowsHigher(this, other)) {
        intersectMax = other.max;
        intersectIncludeMax = other.includeMax;
      } else {
        intersectMax = max;
        intersectIncludeMax = includeMax;
      }

      if (intersectMin == null && intersectMax == null) {
        // Open range.
        return VersionRange();
      }

      // If the range is just a single version.
      if (intersectMin == intersectMax) {
        // Because we already verified that the lower range isn't strictly
        // lower, there must be some overlap.
        assert(intersectIncludeMin && intersectIncludeMax);
        return intersectMin;
      }

      // If we got here, there is an actual range.
      return VersionRange(
          min: intersectMin,
          max: intersectMax,
          includeMin: intersectIncludeMin,
          includeMax: intersectIncludeMax,
          alwaysIncludeMaxPreRelease: true);
    }

    throw ArgumentError('Unknown VersionConstraint type $other.');
  }

  @override
  VersionConstraint union(VersionConstraint other) {
    if (other is Version) {
      if (allows(other)) return this;

      if (other == min) {
        return VersionRange(
            min: min,
            max: max,
            includeMin: true,
            includeMax: includeMax,
            alwaysIncludeMaxPreRelease: true);
      }

      if (other == max) {
        return VersionRange(
            min: min,
            max: max,
            includeMin: includeMin,
            includeMax: true,
            alwaysIncludeMaxPreRelease: true);
      }

      return VersionConstraint.unionOf([this, other]);
    }

    if (other is VersionRange) {
      // If the two ranges don't overlap, we won't be able to create a single
      // VersionRange for both of them.
      var edgesTouch = (max != null &&
              max == other.min &&
              (includeMax || other.includeMin)) ||
          (min != null && min == other.max && (includeMin || other.includeMax));
      if (!edgesTouch && !allowsAny(other)) {
        return VersionConstraint.unionOf([this, other]);
      }

      Version unionMin;
      bool unionIncludeMin;
      if (allowsLower(this, other)) {
        unionMin = min;
        unionIncludeMin = includeMin;
      } else {
        unionMin = other.min;
        unionIncludeMin = other.includeMin;
      }

      Version unionMax;
      bool unionIncludeMax;
      if (allowsHigher(this, other)) {
        unionMax = max;
        unionIncludeMax = includeMax;
      } else {
        unionMax = other.max;
        unionIncludeMax = other.includeMax;
      }

      return VersionRange(
          min: unionMin,
          max: unionMax,
          includeMin: unionIncludeMin,
          includeMax: unionIncludeMax,
          alwaysIncludeMaxPreRelease: true);
    }

    return VersionConstraint.unionOf([this, other]);
  }

  @override
  VersionConstraint difference(VersionConstraint other) {
    if (other.isEmpty) return this;

    if (other is Version) {
      if (!allows(other)) return this;

      if (other == min) {
        if (!includeMin) return this;
        return VersionRange(
            min: min,
            max: max,
            includeMin: false,
            includeMax: includeMax,
            alwaysIncludeMaxPreRelease: true);
      }

      if (other == max) {
        if (!includeMax) return this;
        return VersionRange(
            min: min,
            max: max,
            includeMin: includeMin,
            includeMax: false,
            alwaysIncludeMaxPreRelease: true);
      }

      return VersionUnion.fromRanges([
        VersionRange(
            min: min,
            max: other,
            includeMin: includeMin,
            includeMax: false,
            alwaysIncludeMaxPreRelease: true),
        VersionRange(
            min: other,
            max: max,
            includeMin: false,
            includeMax: includeMax,
            alwaysIncludeMaxPreRelease: true)
      ]);
    } else if (other is VersionRange) {
      if (!allowsAny(other)) return this;

      VersionRange before;
      if (!allowsLower(this, other)) {
        before = null;
      } else if (min == other.min) {
        assert(includeMin && !other.includeMin);
        assert(min != null);
        before = min;
      } else {
        before = VersionRange(
            min: min,
            max: other.min,
            includeMin: includeMin,
            includeMax: !other.includeMin,
            alwaysIncludeMaxPreRelease: true);
      }

      VersionRange after;
      if (!allowsHigher(this, other)) {
        after = null;
      } else if (max == other.max) {
        assert(includeMax && !other.includeMax);
        assert(max != null);
        after = max;
      } else {
        after = VersionRange(
            min: other.max,
            max: max,
            includeMin: !other.includeMax,
            includeMax: includeMax,
            alwaysIncludeMaxPreRelease: true);
      }

      if (before == null && after == null) return VersionConstraint.empty;
      if (before == null) return after;
      if (after == null) return before;
      return VersionUnion.fromRanges([before, after]);
    } else if (other is VersionUnion) {
      var ranges = <VersionRange>[];
      var current = this;

      for (var range in other.ranges) {
        // Skip any ranges that are strictly lower than [current].
        if (strictlyLower(range, current)) continue;

        // If we reach a range strictly higher than [current], no more ranges
        // will be relevant so we can bail early.
        if (strictlyHigher(range, current)) break;

        var difference = current.difference(range);
        if (difference.isEmpty) {
          return VersionConstraint.empty;
        } else if (difference is VersionUnion) {
          // If [range] split [current] in half, we only need to continue
          // checking future ranges against the latter half.
          assert(difference.ranges.length == 2);
          ranges.add(difference.ranges.first);
          current = difference.ranges.last;
        } else {
          current = difference as VersionRange;
        }
      }

      if (ranges.isEmpty) return current;
      return VersionUnion.fromRanges(ranges..add(current));
    }

    throw ArgumentError('Unknown VersionConstraint type $other.');
  }

  @override
  int compareTo(VersionRange other) {
    if (min == null) {
      if (other.min == null) return _compareMax(other);
      return -1;
    } else if (other.min == null) {
      return 1;
    }

    var result = min.compareTo(other.min);
    if (result != 0) return result;
    if (includeMin != other.includeMin) return includeMin ? -1 : 1;

    return _compareMax(other);
  }

  /// Compares the maximum values of `this` and [other].
  int _compareMax(VersionRange other) {
    if (max == null) {
      if (other.max == null) return 0;
      return 1;
    } else if (other.max == null) {
      return -1;
    }

    var result = max.compareTo(other.max);
    if (result != 0) return result;
    if (includeMax != other.includeMax) return includeMax ? 1 : -1;
    return 0;
  }

  @override
  String toString() {
    var buffer = StringBuffer();

    if (min != null) {
      buffer..write(includeMin ? '>=' : '>')..write(min);
    }

    if (max != null) {
      if (min != null) buffer.write(' ');
      if (includeMax) {
        buffer..write('<=')..write(max);
      } else {
        buffer.write('<');
        if (max.isFirstPreRelease) {
          // Since `"<$max"` would parse the same as `"<$max-0"`, we just emit
          // `<$max` to avoid confusing "-0" suffixes.
          buffer.write('${max.major}.${max.minor}.${max.patch}');
        } else {
          buffer.write(max);

          // If `">=$min <$max"` would parse as `">=$min <$max-0"`, add `-*` to
          // indicate that actually does allow pre-release versions.
          var minIsPreReleaseOfMax = min != null &&
              min.isPreRelease &&
              equalsWithoutPreRelease(min, max);
          if (!max.isPreRelease && max.build.isEmpty && !minIsPreReleaseOfMax) {
            buffer.write('-∞');
          }
        }
      }
    }

    if (min == null && max == null) buffer.write('any');
    return buffer.toString();
  }
}

class CompatibleWithVersionRange extends VersionRange {
  CompatibleWithVersionRange(Version version)
      : super._(version, version.nextBreaking.firstPreRelease, true, false);

  @override
  String toString() => '^$min';
}
