content: // Copyright 2023 Google LLC. 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 'package:pub_semver/pub_semver.dart';
  
  import '../deprecation.dart' as dart show Deprecation;
  import '../logger/js_to_dart.dart';
  import 'reflection.dart';
  
  @JS()
  @anonymous
  class Deprecation {
    external String get id;
    external String get status;
    external String? get description;
    external Version? get deprecatedIn;
    external Version? get obsoleteIn;
  
    external factory Deprecation({
      required String id,
      required String status,
      String? description,
      Version? deprecatedIn,
      Version? obsoleteIn,
    });
  }
  
  final Map<String, Deprecation?> deprecations = {
    for (var deprecation in dart.Deprecation.values)
      // `calc-interp` was never actually used, so we don't want to expose it
      // in the JS API.
      if (deprecation != dart.Deprecation.calcInterp)
        deprecation.id: Deprecation(
          id: deprecation.id,
          status: (() => switch (deprecation) {
                dart.Deprecation(isFuture: true) => 'future',
                dart.Deprecation(deprecatedIn: null, obsoleteIn: null) => 'user',
                dart.Deprecation(obsoleteIn: null) => 'active',
                _ => 'obsolete',
              })(),
          description: deprecation.description,
          deprecatedIn: deprecation.deprecatedIn,
          obsoleteIn: deprecation.obsoleteIn,
        ),
  };
  
  /// Parses a list of [deprecations] from JS into an list of Dart [Deprecation]
  /// objects.
  ///
  /// [deprecations] can contain deprecation IDs, JS Deprecation objects, and
  /// (if [supportVersions] is true) [Version]s.
  Iterable<dart.Deprecation>? parseDeprecations(
    JSToDartLogger logger,
    List<Object?>? deprecations, {
    bool supportVersions = false,
  }) {
    if (deprecations == null) return null;
    return () sync* {
      for (var item in deprecations) {
        switch (item) {
          case String id:
            var deprecation = dart.Deprecation.fromId(id);
            if (deprecation == null) {
              logger.warn('Invalid deprecation "$id".');
            } else {
              yield deprecation;
            }
          case Deprecation(:var id):
            var deprecation = dart.Deprecation.fromId(id);
            if (deprecation == null) {
              logger.warn('Invalid deprecation "$id".');
            } else {
              yield deprecation;
            }
          case Version version when supportVersions:
            yield* dart.Deprecation.forVersion(version);
        }
      }
    }();
  }
  
  /// The JavaScript `Version` class.
  final JSClass versionClass = () {
    var jsClass = createJSClass('sass.Version', (
      Object self,
      int major,
      int minor,
      int patch,
    ) {
      return Version(major, minor, patch);
    });
  
    jsClass.defineStaticMethod('parse', (String version) {
      var v = Version.parse(version);
      if (v.isPreRelease || v.build.isNotEmpty) {
        throw FormatException(
          'Build identifiers and prerelease versions not supported.',
        );
      }
      return v;
    });
  
    getJSClass(Version(0, 0, 0)).injectSuperclass(jsClass);
    return jsClass;
  }();
  