content: // Copyright 2018 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:js/js.dart';
  
  import '../../../value.dart';
  import '../../reflection.dart';
  
  @JS()
  class _NodeSassNumber {
    external SassNumber get dartValue;
    external set dartValue(SassNumber dartValue);
  }
  
  /// Creates a new `sass.types.Number` object wrapping [value].
  Object newNodeSassNumber(SassNumber value) =>
      legacyNumberClass.construct([null, null, value]);
  
  /// The JS constructor for the `sass.types.Number` class.
  final JSClass legacyNumberClass = createJSClass('sass.types.Number', (
    _NodeSassNumber thisArg,
    num? value, [
    String? unit,
    SassNumber? dartValue,
  ]) {
    // Either [dartValue] or [value] must be passed.
    thisArg.dartValue = dartValue ?? _parseNumber(value!, unit);
  })
    ..defineMethods({
      'getValue': (_NodeSassNumber thisArg) => thisArg.dartValue.value,
      'setValue': (_NodeSassNumber thisArg, num value) {
        thisArg.dartValue = SassNumber.withUnits(
          value,
          numeratorUnits: thisArg.dartValue.numeratorUnits,
          denominatorUnits: thisArg.dartValue.denominatorUnits,
        );
      },
      'getUnit': (_NodeSassNumber thisArg) =>
          thisArg.dartValue.numeratorUnits.join('*') +
          (thisArg.dartValue.denominatorUnits.isEmpty ? '' : '/') +
          thisArg.dartValue.denominatorUnits.join('*'),
      'setUnit': (_NodeSassNumber thisArg, String unit) {
        thisArg.dartValue = _parseNumber(thisArg.dartValue.value, unit);
      },
    });
  
  /// Parses a [SassNumber] from [value] and [unit], using Node Sass's unit
  /// format.
  SassNumber _parseNumber(num value, String? unit) {
    if (unit == null || unit.isEmpty) return SassNumber(value);
    if (!unit.contains("*") && !unit.contains("/")) {
      return SassNumber(value, unit);
    }
  
    var invalidUnit = ArgumentError.value(unit, 'unit', 'is invalid.');
  
    var operands = unit.split('/');
    if (operands.length > 2) throw invalidUnit;
  
    var numerator = operands[0];
    var denominator = operands.length == 1 ? null : operands[1];
  
    var numeratorUnits = numerator.isEmpty ? <String>[] : numerator.split('*');
    if (numeratorUnits.any((unit) => unit.isEmpty)) throw invalidUnit;
  
    var denominatorUnits =
        denominator == null ? <String>[] : denominator.split('*');
    if (denominatorUnits.any((unit) => unit.isEmpty)) throw invalidUnit;
  
    return SassNumber.withUnits(
      value,
      numeratorUnits: numeratorUnits,
      denominatorUnits: denominatorUnits,
    );
  }
  