content: // Copyright 2020 Google Inc. Use of this source code is governed by an
  // MIT-style license that can be found in the LICENSE file or at
  // https://opensource.org/licenses/MIT.
  
  import 'package:meta/meta.dart';
  
  import '../../util/number.dart';
  import '../../value.dart';
  
  /// A specialized subclass of [SassNumber] for numbers that have no units.
  ///
  /// {@category Value}
  @sealed
  class UnitlessSassNumber extends SassNumber {
    List<String> get numeratorUnits => const [];
  
    List<String> get denominatorUnits => const [];
  
    bool get hasUnits => false;
    bool get hasComplexUnits => false;
  
    UnitlessSassNumber(super.value, [super.asSlash]) : super.protected();
  
    SassNumber withValue(num value) => UnitlessSassNumber(value.toDouble());
  
    SassNumber withSlash(SassNumber numerator, SassNumber denominator) =>
        UnitlessSassNumber(value, (numerator, denominator));
  
    bool hasUnit(String unit) => false;
  
    bool hasCompatibleUnits(SassNumber other) => other is UnitlessSassNumber;
  
    @internal
    bool hasPossiblyCompatibleUnits(SassNumber other) =>
        other is UnitlessSassNumber;
  
    bool compatibleWithUnit(String unit) => true;
  
    SassNumber coerceToMatch(
      SassNumber other, [
      String? name,
      String? otherName,
    ]) =>
        other.withValue(value);
  
    double coerceValueToMatch(
      SassNumber other, [
      String? name,
      String? otherName,
    ]) =>
        value;
  
    SassNumber convertToMatch(
      SassNumber other, [
      String? name,
      String? otherName,
    ]) =>
        other.hasUnits
            // Call this to generate a consistent error message.
            ? super.convertToMatch(other, name, otherName)
            : this;
  
    double convertValueToMatch(
      SassNumber other, [
      String? name,
      String? otherName,
    ]) =>
        other.hasUnits
            // Call this to generate a consistent error message.
            ? super.convertValueToMatch(other, name, otherName)
            : value;
  
    SassNumber coerce(
      List<String> newNumerators,
      List<String> newDenominators, [
      String? name,
    ]) =>
        SassNumber.withUnits(
          value,
          numeratorUnits: newNumerators,
          denominatorUnits: newDenominators,
        );
  
    double coerceValue(
      List<String> newNumerators,
      List<String> newDenominators, [
      String? name,
    ]) =>
        value;
  
    double coerceValueToUnit(String unit, [String? name]) => value;
  
    SassBoolean greaterThan(Value other) {
      if (other is SassNumber) {
        return SassBoolean(fuzzyGreaterThan(value, other.value));
      }
      return super.greaterThan(other);
    }
  
    SassBoolean greaterThanOrEquals(Value other) {
      if (other is SassNumber) {
        return SassBoolean(fuzzyGreaterThanOrEquals(value, other.value));
      }
      return super.greaterThanOrEquals(other);
    }
  
    SassBoolean lessThan(Value other) {
      if (other is SassNumber) {
        return SassBoolean(fuzzyLessThan(value, other.value));
      }
      return super.lessThan(other);
    }
  
    SassBoolean lessThanOrEquals(Value other) {
      if (other is SassNumber) {
        return SassBoolean(fuzzyLessThanOrEquals(value, other.value));
      }
      return super.lessThanOrEquals(other);
    }
  
    SassNumber modulo(Value other) {
      if (other is SassNumber) {
        return other.withValue(moduloLikeSass(value, other.value));
      }
      return super.modulo(other);
    }
  
    Value plus(Value other) {
      if (other is SassNumber) {
        return other.withValue(value + other.value);
      }
      return super.plus(other);
    }
  
    Value minus(Value other) {
      if (other is SassNumber) {
        return other.withValue(value - other.value);
      }
      return super.minus(other);
    }
  
    Value times(Value other) {
      if (other is SassNumber) {
        return other.withValue(value * other.value);
      }
      return super.times(other);
    }
  
    Value dividedBy(Value other) {
      if (other is SassNumber) {
        return other.hasUnits
            ? SassNumber.withUnits(
                value / other.value,
                numeratorUnits: other.denominatorUnits,
                denominatorUnits: other.numeratorUnits,
              )
            : UnitlessSassNumber(value / other.value);
      }
      return super.dividedBy(other);
    }
  
    Value unaryMinus() => UnitlessSassNumber(-value);
  
    bool operator ==(Object other) =>
        other is UnitlessSassNumber && fuzzyEquals(value, other.value);
  
    int get hashCode => hashCache ??= fuzzyHashCode(value);
  }
  